Compare commits
No commits in common. "main" and "36d9e8c02c509dcfe0f0b312c879e8914d5d8d3a" have entirely different histories.
main
...
36d9e8c02c
26 changed files with 158 additions and 1419 deletions
|
@ -1,21 +0,0 @@
|
|||
---
|
||||
|
||||
name: "Bug Report"
|
||||
about: "Something is not working as expected, file a bug report."
|
||||
title: "<short description>"
|
||||
labels:
|
||||
- bug
|
||||
- "help needed"
|
||||
|
||||
---
|
||||
|
||||
# What do you want to achieve?
|
||||
|
||||
# What is the result
|
||||
|
||||
# Further information
|
||||
|
||||
# System information
|
||||
- Rust version:
|
||||
- Operating system:
|
||||
- Contents of all files in `/proc/sys/fs/mqueue`:
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
|
||||
name: "Enhancement"
|
||||
about: "Something could be improved or missing a feature?"
|
||||
title: "<short description>"
|
||||
labels:
|
||||
- enhancement
|
||||
- "help needed"
|
||||
|
||||
---
|
||||
|
||||
# What do you want to achieve?
|
||||
|
||||
# Example of the enhancement
|
||||
|
||||
# Further information
|
258
Cargo.lock
generated
258
Cargo.lock
generated
|
@ -1,21 +1,10 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.51"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
|
||||
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
|
@ -40,36 +29,11 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.0-beta.5"
|
||||
version = "3.0.0-beta.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63"
|
||||
checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
|
@ -80,14 +44,15 @@ dependencies = [
|
|||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
"unicase",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.0.0-beta.5"
|
||||
version = "3.0.0-beta.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3"
|
||||
checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
|
@ -96,24 +61,11 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
|
@ -126,24 +78,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.7.0"
|
||||
version = "1.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
|
||||
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
|
@ -157,88 +103,24 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.108"
|
||||
version = "0.2.97"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
|
||||
|
||||
[[package]]
|
||||
name = "mqrs"
|
||||
version = "0.1.1"
|
||||
version = "0.1.0-dev"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"humantime",
|
||||
"log",
|
||||
"posixmq",
|
||||
"sysvmq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77d9f3521ea8e0641a153b3cddaf008dcbf26acd4ed739a2517295e0760d12c7"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "4.2.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
|
||||
|
||||
[[package]]
|
||||
name = "posixmq"
|
||||
|
@ -275,39 +157,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.32"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
|
||||
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.10"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
@ -316,24 +181,15 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.82"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
|
||||
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysvmq"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"nix",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
|
@ -345,64 +201,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.14.2"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||
checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
|
@ -410,18 +226,18 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
25
Cargo.toml
25
Cargo.toml
|
@ -1,32 +1,13 @@
|
|||
[package]
|
||||
name = "mqrs"
|
||||
version = "0.1.1"
|
||||
version = "0.1.0-dev"
|
||||
authors = ["finga <mqrs@onders.org>"]
|
||||
edition = "2021"
|
||||
repository = "https://git.onders.org/finga/mqrs"
|
||||
edition = "2018"
|
||||
license = "GPL-3.0-or-later"
|
||||
readme = "README.md"
|
||||
description = "A CLI program for interacting with different kinds of message queues."
|
||||
keywords = ["message_queue", "mq", "mqueue", "queue"]
|
||||
categories = ["command-line-utilities"]
|
||||
description = "A CLI program for interacting Posix Message Queues"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
clap = "3.0.0-beta.2"
|
||||
posixmq = "1.0"
|
||||
chrono = "0.4"
|
||||
humantime = "2.1"
|
||||
log = "0.4"
|
||||
env_logger = "0.8"
|
||||
sysvmq = { path = "sysvmq" }
|
||||
|
||||
[workspace]
|
||||
members = ["sysvmq"]
|
||||
|
||||
[package.metadata.deb]
|
||||
extended-description = "`mqrs` is a small cli application to handle different kinds of message queues."
|
||||
assets = [
|
||||
["target/release/mqrs", "usr/bin/", "755"],
|
||||
["README.md", "usr/share/doc/cargo-deb/README.md", "644"],
|
||||
["mqrs.1", "/usr/share/man/man1/mqrs.1", "644"],
|
||||
]
|
||||
|
|
49
INSTALL.md
49
INSTALL.md
|
@ -1,49 +0,0 @@
|
|||
# Installation
|
||||
To build `mqrs` having the rust toolchain installed is mandatory.
|
||||
|
||||
## Install Rust
|
||||
Install the Rust toolchain from [rustup.rs](https://rustup.rs).
|
||||
|
||||
## Build `mqrs`
|
||||
`mqrs` can be built for development:
|
||||
```sh
|
||||
cargo b
|
||||
```
|
||||
|
||||
or for releasing:
|
||||
```sh
|
||||
cargo b --release
|
||||
```
|
||||
|
||||
## Build the `mqrs` Debian package
|
||||
For that [`cargo-deb`](https://github.com/mmstick/cargo-deb) is
|
||||
required, which can be installed with:
|
||||
```sh
|
||||
cargo install cargo-deb
|
||||
```
|
||||
|
||||
A Debian package can be built with:
|
||||
```sh
|
||||
cargo deb
|
||||
```
|
||||
|
||||
## Install `mqrs`
|
||||
When a Rust toolchain installed you can also install `mqrs`
|
||||
directly without cloning it manually:
|
||||
``` sh
|
||||
cargo install --git https://git.onders.org/finga/mqrs.git mqrs
|
||||
```
|
||||
|
||||
or from within the project:
|
||||
```sh
|
||||
cargo install mqrs
|
||||
```
|
||||
|
||||
## Run `mqrs`
|
||||
`mqrs` can either be run from the project directory with:
|
||||
```sh
|
||||
cargo b
|
||||
```
|
||||
|
||||
or you can copy the produced binary somewhere else or link to them
|
||||
from `target/{debug,release}/mqrs` depending on which one you built.
|
84
README.md
84
README.md
|
@ -1,84 +0,0 @@
|
|||
# mqrs
|
||||
`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
|
||||
[`INSTALL.md`](INSTALL.md).
|
||||
|
||||
## 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
|
||||
|
||||
If a command is clearly distinguishable from all the others,
|
||||
it does not have to be completed further.
|
||||
|
||||
### POSIX message queues
|
||||
The POSIX backend supports six commands: `create`, `info`, `list`,
|
||||
`unlink`, `send` and `recv`.
|
||||
|
||||
#### Create a message queue
|
||||
Use the `create` command to create a new POSIX message queue. Following
|
||||
optional arguments are supported:
|
||||
- `-c`, `--capacity`: Maximum number of messages in the queue
|
||||
- `-m`, `--mode`: Permissions (octal) to create the queue with
|
||||
- `-s`, `--msgsize`: Message size in bytes
|
||||
|
||||
#### Print information about a message queue
|
||||
Use the `info` command to print further information about a message
|
||||
queue.
|
||||
|
||||
#### List all message queues
|
||||
Use the `list` command to print a list of all message
|
||||
queues. Following option argument is supported:
|
||||
- `-a`, `--all`: Print all available information
|
||||
|
||||
#### Delete a message queue
|
||||
Use the `unlink` command to delete a message queue.
|
||||
|
||||
#### Send a message to a queue
|
||||
Use the `send` command to send a message to a message queue. Following
|
||||
optional arguments are supported:
|
||||
- `-n`, `--non-blocking`: Do not block
|
||||
- `-d`, `--deadline <deadline>`: Deadline until messages are sent
|
||||
(format: `%Y-%m-%d %H:%M:%S`)
|
||||
- `-p`, `--priority <priority>`: Set a different priority than
|
||||
default, priority >= 0 [default: 0]
|
||||
- `-o`, `--timeout <timeout>`: As for example in "5h 23min 42ms"
|
||||
|
||||
#### Receive a message from a queue
|
||||
Use the `recv` command to receive one or more messages from a message
|
||||
queue. Following optional arguments are supported:
|
||||
- `-f`, `--follow`: Print messages as they are received
|
||||
- `-n`, `--non-blocking`: Do not block
|
||||
- `-t`, `--timestamp`: Print a timestamp before each message
|
||||
- `-d`, `--deadline <deadline>`: Deadline until messages are received
|
||||
(format: `%Y-%m-%d %H:%M:%S`)
|
||||
- `-o,` `--timeout <timeout>`: As for example in "5h 23min 42ms"
|
||||
|
||||
### SysV IPC message queues
|
||||
The SysV IPC backend supports two commands: `create` and `unlink`.
|
||||
|
||||
#### Create a message queue
|
||||
Use the `create` command to create a new SysV IPC message
|
||||
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:
|
||||
- `-i`, `--id <id>`: Id of the queue
|
||||
- `-k`, `--key <key>`: Key of the queue
|
326
mqrs.1
326
mqrs.1
|
@ -1,326 +0,0 @@
|
|||
.\" Manpage for mqrs
|
||||
.TH man 1 "7 July 2021" "0.1.1" "mqrs man page"
|
||||
.SH NAME
|
||||
mqrs \- Handle POSIX message queues
|
||||
.SH SYNOPSIS
|
||||
.B mqrs [\-h] [\-\-help] [\-v] [\-\-verbose] [\-V] [\-\-version] [SUBCOMMAND]
|
||||
.SH DESCRIPTION
|
||||
.B mqrs
|
||||
is a small cli program to handle message queues. Depending on which
|
||||
backend you want to use there are different subsets of
|
||||
subcommands. Following backends are supported:
|
||||
.B posix\
|
||||
and
|
||||
.B sysv\
|
||||
.
|
||||
|
||||
If a command is clearly distinguishable from all the others, it does
|
||||
not have to be completed further.
|
||||
.SH OPTIONS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output, multiple -v options increase the verbosity
|
||||
(max. 3)
|
||||
.TP 8
|
||||
.B \-V, \-\-version
|
||||
Prints version information
|
||||
.SH POSIX MESSAGE QUEUE SUBCOMMANDS
|
||||
The POSIX backend supports six commands:
|
||||
.B create\
|
||||
,
|
||||
.B info\
|
||||
,
|
||||
.B list\
|
||||
,
|
||||
.B unlink\
|
||||
,
|
||||
.B send
|
||||
and
|
||||
.B recv
|
||||
.
|
||||
.SS posix create [FLAGS] [OPTIONS] \fI<QUEUE>\fP
|
||||
Create a new POSIX message queue.
|
||||
.TP 8
|
||||
.SS ARGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \fI<QUEUE>\fP
|
||||
Name of the new queue
|
||||
.RE
|
||||
.TP 8
|
||||
.SS FLAGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output
|
||||
.TP 8
|
||||
.SS OPTIONS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-c, \-\-capacity \fI<capacity>\fP
|
||||
Maximum number of messages in the queue
|
||||
.TP 8
|
||||
.B \-s, \-\-msgsize \fI<msgsize>\fP
|
||||
Message size in bytes
|
||||
.TP 8
|
||||
.B \-m, \-\-mode \fI<mode>\fP
|
||||
Permissions (octal) to create the queue with
|
||||
.RE
|
||||
.SS posix 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 posix info [FLAGS] \fI<QUEUE>\fP
|
||||
Print further information about an existing message queue.
|
||||
.TP 8
|
||||
.SS ARGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \fI<QUEUE>\fP
|
||||
Name of the queue
|
||||
.RE
|
||||
.TP 8
|
||||
.SS FLAGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output
|
||||
.RE
|
||||
.SS posix list [FLAGS]
|
||||
Print a list of all existing POSIX message queues.
|
||||
.TP 8
|
||||
.SS FLAGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output
|
||||
.TP 8
|
||||
.B \-a, \-\-all
|
||||
Print all available information
|
||||
.RE
|
||||
.SS posix recv [FLAGS] [OPTIONS] \fI<QUEUE>\fP
|
||||
Receive and print one or more messages message from a message queue.
|
||||
.TP 8
|
||||
.SS ARGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \fI<QUEUE>\fP
|
||||
Name of the queue
|
||||
.RE
|
||||
.TP 8
|
||||
.SS FLAGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-f, \-\-follow
|
||||
Print messages as they are received
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-n, \-\-non\-blocking
|
||||
Do not block
|
||||
.TP 8
|
||||
.B \-t, \-\-timestamp
|
||||
Print a timestamp before each message
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output
|
||||
.RE
|
||||
.TP 8
|
||||
.SS OPTIONS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-d, \-\-deadline \fI<deadline>\fP
|
||||
Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
|
||||
.TP 8
|
||||
.B \-o, \-\-timeout \fI<timeout>\fP
|
||||
Timeout as for example in "5h 23min 42ms"
|
||||
.RE
|
||||
.SS posix send [FLAGS] [OPTIONS] \fI<QUEUE>\fP \fI<MESSAGE>\fP
|
||||
Send a message to a message queue.
|
||||
.TP 8
|
||||
.SS ARGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \fI<QUEUE>\fP
|
||||
Name of the queue
|
||||
.TP 8
|
||||
.B \fI<MESSAGE>\fP
|
||||
Message to be sent to the queue
|
||||
.RE
|
||||
.TP 8
|
||||
.SS FLAGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-n, \-\-non\-blocking
|
||||
Do not block
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output
|
||||
.RE
|
||||
.TP 8
|
||||
.SS OPTIONS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-d, \-\-deadline \fI<deadline>\fP
|
||||
Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
|
||||
.TP 8
|
||||
.B \-p, \-\-priority \fI<priority>\fP
|
||||
Set a different priority than default, priority >= 0 [default: 0]
|
||||
.TP 8
|
||||
.B \-o, \-\-timeout \fI<timeout>\fP
|
||||
Timeout as for example in "5h 23min 42ms"
|
||||
.RE
|
||||
.SS posix unlink [FLAGS] \fI<QUEUE>\fP
|
||||
Delete an existing POSIX message queue.
|
||||
.TP 8
|
||||
.SS ARGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \fI<QUEUE>\fP
|
||||
Name of the queue
|
||||
.RE
|
||||
.TP 8
|
||||
.SS FLAGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output
|
||||
.RE
|
||||
.SH SYSV IPC MESSAGE QUEUE SUBCOMMANDS
|
||||
The SysV IPC backend supports four commands:
|
||||
.B create\
|
||||
,
|
||||
.B info\
|
||||
,
|
||||
.B list
|
||||
and
|
||||
.B unlink\
|
||||
.
|
||||
.SS sysv create [FLAGS] [OPTIONS] \fI<KEY>\fP
|
||||
Create a new SysV IPC message queue.
|
||||
.TP 8
|
||||
.SS ARGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \fI<KEY>\fP
|
||||
Key of the new queue
|
||||
.RE
|
||||
.TP 8
|
||||
.SS FLAGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output
|
||||
.TP 8
|
||||
.SS OPTIONS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-m, \-\-mode \fI<mode>\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<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
|
||||
.SS ARGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \fI<KEY>\fP
|
||||
Key of the new queue
|
||||
.RE
|
||||
.TP 8
|
||||
.SS FLAGS
|
||||
.RS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Prints help information
|
||||
.TP 8
|
||||
.B \-v, \-\-verbose
|
||||
Produce verbose output
|
||||
.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
|
||||
.SH SEE ALSO
|
||||
mq_overview(7), sysvipc(7)
|
||||
.SH BUGS
|
||||
No known bugs.
|
||||
.SH AUTHOR
|
||||
finga (mqrs@onders.org)
|
26
src/cli.rs
Normal file
26
src/cli.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use crate::{create::Create, info::Info, send::Send, unlink::Unlink};
|
||||
use clap::{crate_authors, crate_version, AppSettings, Clap};
|
||||
|
||||
#[derive(Clap, Debug)]
|
||||
#[clap(
|
||||
version = crate_version!(),
|
||||
author = crate_authors!(", "),
|
||||
setting = AppSettings::SubcommandRequiredElseHelp,
|
||||
global_setting = AppSettings::VersionlessSubcommands,
|
||||
global_setting = AppSettings::InferSubcommands,
|
||||
)]
|
||||
pub struct Opts {
|
||||
/// Produce verbose output
|
||||
#[clap(short, long, global = true)]
|
||||
pub verbose: bool,
|
||||
#[clap(subcommand)]
|
||||
pub command: Command,
|
||||
}
|
||||
|
||||
#[derive(Clap, Debug)]
|
||||
pub enum Command {
|
||||
Create(Create),
|
||||
Info(Info),
|
||||
Unlink(Unlink),
|
||||
Send(Send),
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use log::{info, log_enabled, Level::Info};
|
||||
use clap::Clap;
|
||||
use posixmq::PosixMq;
|
||||
use std::fs;
|
||||
|
||||
/// Create a POSIX message queue
|
||||
#[derive(Debug, Parser)]
|
||||
#[derive(Clap, Debug)]
|
||||
pub struct Create {
|
||||
/// Permissions (octal) to create the queue with
|
||||
#[clap(short, long)]
|
||||
#[clap(short = 'p', long)]
|
||||
mode: Option<String>,
|
||||
/// Maximum number of messages in the queue
|
||||
#[clap(short, long)]
|
||||
|
@ -16,31 +15,31 @@ pub struct Create {
|
|||
/// Message size in bytes
|
||||
#[clap(short = 's', long)]
|
||||
msgsize: Option<usize>,
|
||||
/// Name of the new queue
|
||||
#[clap(value_name = "QUEUE")]
|
||||
/// Name of the queue
|
||||
#[clap(value_name = "QNAME")]
|
||||
queue: String,
|
||||
}
|
||||
|
||||
fn msgsize_default() -> usize {
|
||||
match fs::read_to_string("/proc/sys/fs/mqueue/msgsize_default") {
|
||||
Ok(m) => m.trim().parse::<usize>().expect("can never fail"),
|
||||
Ok(m) => m.trim().parse::<usize>().unwrap(), // should never fail
|
||||
_ => 8192,
|
||||
}
|
||||
}
|
||||
|
||||
fn msg_default() -> usize {
|
||||
match fs::read_to_string("/proc/sys/fs/mqueue/msg_default") {
|
||||
Ok(m) => m.trim().parse::<usize>().expect("can never fail"),
|
||||
Ok(m) => m.trim().parse::<usize>().unwrap(), // should never fail
|
||||
_ => 10,
|
||||
}
|
||||
}
|
||||
|
||||
impl Create {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
pub fn run(&self, verbose: bool) -> Result<()> {
|
||||
let mq = &mut posixmq::OpenOptions::readonly();
|
||||
|
||||
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))
|
||||
|
@ -48,15 +47,15 @@ impl Create {
|
|||
.create_new()
|
||||
.open(&self.queue)?;
|
||||
|
||||
if log_enabled!(Info) {
|
||||
if verbose {
|
||||
let mq = PosixMq::open(&self.queue)?;
|
||||
let attributes = mq.attributes()?;
|
||||
|
||||
info!("Created message queue: {} with attributes msgsize: {}, capacity: {}, current_messages: {}",
|
||||
self.queue,
|
||||
attributes.max_msg_len,
|
||||
attributes.capacity,
|
||||
attributes.current_messages);
|
||||
println!("Created message queue: {} with attributes msgsize: {}, capacity: {}, current_messages: {}",
|
||||
&self.queue,
|
||||
&attributes.max_msg_len,
|
||||
&attributes.capacity,
|
||||
&attributes.current_messages);
|
||||
}
|
||||
|
||||
Ok(())
|
|
@ -1,13 +1,13 @@
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use clap::Clap;
|
||||
use posixmq::PosixMq;
|
||||
|
||||
/// Print information about an existing message queue
|
||||
#[derive(Debug, Parser)]
|
||||
#[derive(Clap, Debug)]
|
||||
pub struct Info {
|
||||
/// Name of the queue
|
||||
#[clap(value_name = "QUEUE")]
|
||||
queue: String,
|
||||
#[clap(value_name = "QNAME")]
|
||||
pub queue: String,
|
||||
}
|
||||
|
||||
impl Info {
|
||||
|
@ -16,7 +16,7 @@ impl Info {
|
|||
|
||||
println!(
|
||||
"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(())
|
84
src/main.rs
84
src/main.rs
|
@ -1,82 +1,22 @@
|
|||
use anyhow::Result;
|
||||
use clap::{crate_authors, crate_version, AppSettings, Parser};
|
||||
use clap::Clap;
|
||||
|
||||
mod posix;
|
||||
mod sysv;
|
||||
mod cli;
|
||||
mod create;
|
||||
mod info;
|
||||
mod send;
|
||||
mod unlink;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
enum Backend {
|
||||
/// Handle POSIX message queues
|
||||
#[clap(subcommand)]
|
||||
Posix(PosixCommand),
|
||||
/// Handle SysV message queues
|
||||
#[clap(subcommand)]
|
||||
Sysv(SysvCommand),
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
enum PosixCommand {
|
||||
Create(posix::Create),
|
||||
Info(posix::Info),
|
||||
List(posix::List),
|
||||
Unlink(posix::Unlink),
|
||||
Send(posix::Send),
|
||||
Recv(posix::Recv),
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
enum SysvCommand {
|
||||
Create(sysv::Create),
|
||||
Info(sysv::Info),
|
||||
List(sysv::List),
|
||||
Unlink(sysv::Unlink),
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(
|
||||
version = crate_version!(),
|
||||
author = crate_authors!(", "),
|
||||
setting = AppSettings::SubcommandRequiredElseHelp,
|
||||
global_setting = AppSettings::PropagateVersion,
|
||||
global_setting = AppSettings::InferSubcommands,
|
||||
)]
|
||||
struct Opts {
|
||||
/// Produce verbose output, multiple -v options increase the verbosity (max. 3)
|
||||
#[clap(short, long, global = true, parse(from_occurrences))]
|
||||
verbose: u32,
|
||||
/// Backend to be used
|
||||
#[clap(subcommand)]
|
||||
backend: Backend,
|
||||
}
|
||||
use cli::{Command, Opts};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let opts: Opts = Opts::parse();
|
||||
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(
|
||||
match opts.verbose {
|
||||
0 => "warn",
|
||||
1 => "info",
|
||||
2 => "debug",
|
||||
_ => "trace",
|
||||
},
|
||||
))
|
||||
.init();
|
||||
|
||||
match opts.backend {
|
||||
Backend::Posix(p) => match p {
|
||||
PosixCommand::Create(c) => c.run()?,
|
||||
PosixCommand::Info(i) => i.run()?,
|
||||
PosixCommand::List(l) => l.run()?,
|
||||
PosixCommand::Unlink(u) => u.run()?,
|
||||
PosixCommand::Send(s) => s.run()?,
|
||||
PosixCommand::Recv(r) => r.run()?,
|
||||
},
|
||||
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()?,
|
||||
},
|
||||
match opts.command {
|
||||
Command::Create(c) => c.run(opts.verbose)?,
|
||||
Command::Info(i) => i.run()?,
|
||||
Command::Unlink(u) => u.run(opts.verbose)?,
|
||||
Command::Send(s) => s.run(opts.verbose)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use chrono::{DateTime, Local};
|
||||
use clap::Parser;
|
||||
use log::warn;
|
||||
use std::{fs, os::unix::fs::PermissionsExt};
|
||||
|
||||
/// Print a list of existing message queues
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct List {
|
||||
/// Show all parameters
|
||||
#[clap(short, long)]
|
||||
all: bool,
|
||||
}
|
||||
|
||||
impl List {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
match self.all {
|
||||
false => println!("Name"),
|
||||
true => println!(
|
||||
"{0: <10} {1: <10} {2: <12} {3: <26} {4: <26}",
|
||||
"Name", "Size", "Permissions", "Modified", "Accessed",
|
||||
),
|
||||
}
|
||||
|
||||
for mq in fs::read_dir("/dev/mqueue")? {
|
||||
match mq {
|
||||
Ok(mq) => {
|
||||
print!(
|
||||
"/{0: <10}",
|
||||
mq.file_name().into_string().map_err(|e| anyhow!(
|
||||
"Could not convert queue name to string: {:?}",
|
||||
e
|
||||
))?
|
||||
);
|
||||
|
||||
if self.all {
|
||||
let metadata = mq.metadata()?;
|
||||
let modified: DateTime<Local> = metadata.modified()?.into();
|
||||
let accessed: DateTime<Local> = metadata.accessed()?.into();
|
||||
|
||||
print!(
|
||||
"{0: <10} {1: <12o} {2: <26} {3: <26}",
|
||||
metadata.len(),
|
||||
metadata.permissions().mode(),
|
||||
modified,
|
||||
accessed,
|
||||
);
|
||||
}
|
||||
|
||||
println!();
|
||||
}
|
||||
Err(e) => warn!("Could not read file: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
mod create;
|
||||
mod info;
|
||||
mod list;
|
||||
mod recv;
|
||||
mod send;
|
||||
mod unlink;
|
||||
|
||||
pub use create::Create;
|
||||
pub use info::Info;
|
||||
pub use list::List;
|
||||
pub use recv::Recv;
|
||||
pub use send::Send;
|
||||
pub use unlink::Unlink;
|
|
@ -1,85 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use chrono::{DateTime, Local};
|
||||
use clap::Parser;
|
||||
use humantime::Duration;
|
||||
use log::info;
|
||||
use posixmq::PosixMq;
|
||||
use std::str;
|
||||
|
||||
/// Receive and print a message from a message queue
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Recv {
|
||||
/// Do not block
|
||||
#[clap(short, long)]
|
||||
non_blocking: bool,
|
||||
/// Print messages as they are received
|
||||
#[clap(short, long)]
|
||||
follow: bool,
|
||||
/// Print a timestamp before each message
|
||||
#[clap(short, long)]
|
||||
timestamp: bool,
|
||||
/// Timeout, example "5h 23min 42ms"
|
||||
#[clap(short = 'o', long, conflicts_with = "deadline")]
|
||||
timeout: Option<String>,
|
||||
/// Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
|
||||
#[clap(short, long, conflicts_with = "timeout")]
|
||||
deadline: Option<String>,
|
||||
/// Name of the queue
|
||||
#[clap(value_name = "QUEUE")]
|
||||
queue: String,
|
||||
}
|
||||
|
||||
fn print_message(priority: u32, length: usize, timestamp: bool, msg: &str) {
|
||||
info!("Priority: {}, length: {}", priority, length);
|
||||
|
||||
if timestamp {
|
||||
println!("{}", Local::now());
|
||||
}
|
||||
|
||||
println!("{}", msg);
|
||||
}
|
||||
|
||||
impl Recv {
|
||||
fn receive(&self, mq: &PosixMq) -> Result<()> {
|
||||
let mut buf = vec![0; mq.attributes()?.max_msg_len];
|
||||
|
||||
if let Some(timeout) = &self.timeout {
|
||||
let (prio, len) = mq.recv_timeout(&mut buf, *timeout.parse::<Duration>()?)?;
|
||||
|
||||
print_message(prio, len, self.timestamp, str::from_utf8(&buf)?);
|
||||
} else if let Some(deadline) = &self.deadline {
|
||||
let (prio, len) = mq.recv_deadline(
|
||||
&mut buf,
|
||||
DateTime::parse_from_str(deadline, "%Y-%m-%d %H:%M:%S")?.into(),
|
||||
)?;
|
||||
|
||||
print_message(prio, len, self.timestamp, str::from_utf8(&buf)?);
|
||||
} else {
|
||||
let (prio, len) = mq.recv(&mut buf)?;
|
||||
|
||||
print_message(prio, len, self.timestamp, str::from_utf8(&buf)?);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(&self) -> Result<()> {
|
||||
let mq = &mut posixmq::OpenOptions::readonly();
|
||||
|
||||
if self.non_blocking {
|
||||
mq.nonblocking();
|
||||
}
|
||||
|
||||
let mq = mq.open(&self.queue)?;
|
||||
|
||||
if self.follow {
|
||||
loop {
|
||||
self.receive(&mq)?;
|
||||
}
|
||||
} else {
|
||||
self.receive(&mq)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use chrono::DateTime;
|
||||
use clap::Parser;
|
||||
use humantime::Duration;
|
||||
use log::info;
|
||||
|
||||
/// Send a message to a message queue
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Send {
|
||||
/// Set a different priority, priority >= 0
|
||||
#[clap(short, long, default_value = "0")]
|
||||
priority: u32,
|
||||
/// Do not block
|
||||
#[clap(short, long)]
|
||||
non_blocking: bool,
|
||||
/// Timeout, example "5h 23min 42ms"
|
||||
#[clap(short = 'o', long, conflicts_with = "deadline")]
|
||||
timeout: Option<String>,
|
||||
/// Deadline until messages are sent (format: "%Y-%m-%d %H:%M:%S")
|
||||
#[clap(short, long, conflicts_with = "timeout")]
|
||||
deadline: Option<String>,
|
||||
/// Name of the queue
|
||||
#[clap(value_name = "QUEUE")]
|
||||
queue: String,
|
||||
/// Message to be sent to the queue
|
||||
#[clap(value_name = "MESSAGE")]
|
||||
msg: String,
|
||||
}
|
||||
|
||||
impl Send {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
let mq = &mut posixmq::OpenOptions::writeonly();
|
||||
|
||||
if self.non_blocking {
|
||||
mq.nonblocking();
|
||||
}
|
||||
|
||||
if let Some(timeout) = &self.timeout {
|
||||
mq.open(&self.queue)?.send_timeout(
|
||||
self.priority,
|
||||
self.msg.as_bytes(),
|
||||
*timeout.parse::<Duration>()?,
|
||||
)?;
|
||||
|
||||
info!("Sent message: \"{}\" to queue: {}", self.msg, self.queue);
|
||||
} else if let Some(deadline) = &self.deadline {
|
||||
mq.open(&self.queue)?.send_deadline(
|
||||
self.priority,
|
||||
self.msg.as_bytes(),
|
||||
DateTime::parse_from_str(deadline, "%Y-%m-%d %H:%M:%S")?.into(),
|
||||
)?;
|
||||
|
||||
info!("Sent message: \"{}\" to queue: {}", self.msg, self.queue);
|
||||
} else {
|
||||
mq.open(&self.queue)?
|
||||
.send(self.priority, self.msg.as_bytes())?;
|
||||
|
||||
info!("Sent message: \"{}\" to queue: {}", self.msg, self.queue);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
|
||||
/// Delete a message queue
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Unlink {
|
||||
/// Name of the queue
|
||||
#[clap(value_name = "QUEUE")]
|
||||
pub queue: String,
|
||||
}
|
||||
|
||||
impl Unlink {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
posixmq::remove_queue(&self.queue)?;
|
||||
|
||||
info!("Removed message queue: {}", self.queue);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
38
src/send.rs
Normal file
38
src/send.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use anyhow::Result;
|
||||
use clap::Clap;
|
||||
|
||||
/// Send a message to a message queue
|
||||
#[derive(Clap, Debug)]
|
||||
pub struct Send {
|
||||
/// Use priority PRIO, PRIO >= 0
|
||||
#[clap(short, long, default_value = "0")]
|
||||
pub priority: u32,
|
||||
/// Do not block
|
||||
#[clap(short, long)]
|
||||
pub non_blocking: bool,
|
||||
/// Name of the queue
|
||||
#[clap(value_name = "QNAME")]
|
||||
pub queue: String,
|
||||
/// Message to be sent to the queue
|
||||
#[clap(value_name = "MESSAGE")]
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
impl Send {
|
||||
pub fn run(&self, verbose: bool) -> Result<()> {
|
||||
let mq = &mut posixmq::OpenOptions::writeonly();
|
||||
|
||||
if self.non_blocking {
|
||||
mq.nonblocking();
|
||||
}
|
||||
|
||||
mq.open(&self.queue)?
|
||||
.send(self.priority, &self.msg.as_bytes())?;
|
||||
|
||||
if verbose {
|
||||
println!("Sent message: \"{}\" to queue: {}", &self.msg, &self.queue);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use sysvmq::SysvMq;
|
||||
|
||||
/// Create a SysV message queue
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Create {
|
||||
/// Permissions (octal) to create the queue with (default: 0644)
|
||||
#[clap(short, long)]
|
||||
mode: Option<String>,
|
||||
/// Key of the new queue
|
||||
#[clap(value_name = "KEY")]
|
||||
key: i32,
|
||||
}
|
||||
|
||||
impl Create {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
let mut mq = SysvMq::<String>::new();
|
||||
|
||||
if let Some(m) = &self.mode {
|
||||
mq.mode(i32::from_str_radix(m, 8)?);
|
||||
}
|
||||
|
||||
mq.create(self.key)?;
|
||||
|
||||
info!("SysV message queue created, key: {}, id: {}", mq.key, mq.id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
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(())
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
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(())
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
mod create;
|
||||
mod info;
|
||||
mod list;
|
||||
mod unlink;
|
||||
|
||||
pub use create::Create;
|
||||
pub use info::Info;
|
||||
pub use list::List;
|
||||
pub use unlink::Unlink;
|
|
@ -1,37 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
|
||||
/// Delete a message queue
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Unlink {
|
||||
/// 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>,
|
||||
}
|
||||
|
||||
impl Unlink {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
if let Some(id) = self.id {
|
||||
sysvmq::unlink_id(id)?;
|
||||
|
||||
info!("Removed message queue with id: {}", id);
|
||||
} else if let Some(key) = self.key {
|
||||
let id = sysvmq::id_from_key(key)?;
|
||||
|
||||
sysvmq::unlink_id(id)?;
|
||||
|
||||
info!("Removed message queue key: {} (id: {})", key, id);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
22
src/unlink.rs
Normal file
22
src/unlink.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use anyhow::Result;
|
||||
use clap::Clap;
|
||||
|
||||
/// Delete a message queue
|
||||
#[derive(Clap, Debug)]
|
||||
pub struct Unlink {
|
||||
/// Name of the queue
|
||||
#[clap(value_name = "QNAME")]
|
||||
pub queue: String,
|
||||
}
|
||||
|
||||
impl Unlink {
|
||||
pub fn run(&self, verbose: bool) -> Result<()> {
|
||||
posixmq::remove_queue(&self.queue)?;
|
||||
|
||||
if verbose {
|
||||
println!("Removed message queue: {}", &self.queue);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
2
sysvmq/.gitignore
vendored
2
sysvmq/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
/target
|
||||
Cargo.lock
|
|
@ -1,12 +0,0 @@
|
|||
[package]
|
||||
name = "sysvmq"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
authors = ["finga <mqrs@onders.org>"]
|
||||
repository = "https://git.onders.org/finga/mqrs"
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.98"
|
||||
thiserror = "1.0.26"
|
||||
nix = "0.21.0"
|
|
@ -1,179 +0,0 @@
|
|||
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,
|
||||
};
|
||||
use nix::errno::{errno, Errno};
|
||||
use std::{marker::PhantomData, mem::MaybeUninit, ptr};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SysvMqError {
|
||||
#[error("SysV message queue: {0}")]
|
||||
ErrnoError(&'static str),
|
||||
}
|
||||
|
||||
/// IPC bit flags
|
||||
#[repr(i32)]
|
||||
pub enum Flags {
|
||||
/// Create key if key does not exist.
|
||||
CreateKey = IPC_CREAT,
|
||||
/// Fail if key exists.
|
||||
Exclusive = IPC_EXCL,
|
||||
/// Return error on wait.
|
||||
NoWait = IPC_NOWAIT,
|
||||
/// No error if message is too big.
|
||||
NoError = MSG_NOERROR,
|
||||
/// Receive any message except of specified type.
|
||||
Except = MSG_EXCEPT,
|
||||
/// Copy (not remove) all queue messages.
|
||||
Copy = MSG_COPY,
|
||||
/// Private key (Special key value).
|
||||
Private = IPC_PRIVATE,
|
||||
}
|
||||
|
||||
/// Commands for `msgctl()`
|
||||
#[repr(i32)]
|
||||
pub enum ControlCommands {
|
||||
/// Remove identifier (Control command for `msgctl`, `semctl`, and `shmctl`).
|
||||
Remove = IPC_RMID,
|
||||
/// Set `ipc_perm` options (Control command for `msgctl`, `semctl`, and `shmctl`).
|
||||
SetPerm = IPC_SET,
|
||||
/// Get `ipc_perm` options (Control command for `msgctl`, `semctl`, and `shmctl`).
|
||||
GetPerm = IPC_STAT,
|
||||
/// See ipcs (Control command for `msgctl`, `semctl`, and `shmctl`).
|
||||
IpcInfo = IPC_INFO,
|
||||
/// IPCS control command.
|
||||
Stat = MSG_STAT,
|
||||
/// IPCS control command.
|
||||
MsgInfo = MSG_INFO,
|
||||
}
|
||||
|
||||
pub fn unlink_id(id: i32) -> Result<(), SysvMqError> {
|
||||
let res = unsafe {
|
||||
msgctl(
|
||||
id,
|
||||
ControlCommands::Remove as i32,
|
||||
ptr::null::<msqid_ds>() as *mut msqid_ds,
|
||||
)
|
||||
};
|
||||
|
||||
match res {
|
||||
-1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id_from_key(key: i32) -> Result<i32, 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::<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 id: i32,
|
||||
pub key: i32,
|
||||
message_mask: i32,
|
||||
mode: i32,
|
||||
types: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> SysvMq<T> {
|
||||
pub fn create(&mut self, key: i32) -> Result<&Self, SysvMqError> {
|
||||
self.key = key;
|
||||
self.id = unsafe { msgget(self.key, Flags::CreateKey as i32 | self.mode) };
|
||||
|
||||
match self.id {
|
||||
-1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())),
|
||||
_ => Ok(self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(mut self, key: i32) -> Result<Self, SysvMqError> {
|
||||
self.key = key;
|
||||
self.id = unsafe { msgget(self.key, self.mode) };
|
||||
|
||||
match self.id {
|
||||
-1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())),
|
||||
_ => Ok(self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mode(&mut self, mode: i32) -> &Self {
|
||||
self.mode = mode;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn nonblocking(&mut self) -> &Self {
|
||||
self.message_mask |= Flags::NoWait as i32;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
SysvMq {
|
||||
id: -1,
|
||||
key: 0,
|
||||
message_mask: 0,
|
||||
mode: 0o644,
|
||||
types: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for SysvMq<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue