diff --git a/.gitea/issue_template/bug.md b/.gitea/issue_template/bug.md deleted file mode 100644 index 7257e02..0000000 --- a/.gitea/issue_template/bug.md +++ /dev/null @@ -1,21 +0,0 @@ ---- - -name: "Bug Report" -about: "Something is not working as expected, file a bug report." -title: "" -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`: diff --git a/.gitea/issue_template/enhancement.md b/.gitea/issue_template/enhancement.md deleted file mode 100644 index 551a59d..0000000 --- a/.gitea/issue_template/enhancement.md +++ /dev/null @@ -1,16 +0,0 @@ ---- - -name: "Enhancement" -about: "Something could be improved or missing a feature?" -title: "" -labels: -- enhancement -- "help needed" - ---- - -# What do you want to achieve? - -# Example of the enhancement - -# Further information diff --git a/Cargo.lock b/Cargo.lock index dc36e4c..a76a2d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index f8005b0..4222fbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,32 +1,13 @@ [package] name = "mqrs" -version = "0.1.1" +version = "0.1.0-dev" authors = ["finga "] -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"], -] diff --git a/INSTALL.md b/INSTALL.md deleted file mode 100644 index 7b638ed..0000000 --- a/INSTALL.md +++ /dev/null @@ -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. diff --git a/README.md b/README.md deleted file mode 100644 index 9e73663..0000000 --- a/README.md +++ /dev/null @@ -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 until messages are sent - (format: `%Y-%m-%d %H:%M:%S`) -- `-p`, `--priority `: Set a different priority than - default, priority >= 0 [default: 0] -- `-o`, `--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 until messages are received - (format: `%Y-%m-%d %H:%M:%S`) -- `-o,` `--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 of the queue -- `-k`, `--key `: Key of the queue diff --git a/mqrs.1 b/mqrs.1 deleted file mode 100644 index ce48a87..0000000 --- a/mqrs.1 +++ /dev/null @@ -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\fP -Create a new POSIX message queue. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\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\fP -Maximum number of messages in the queue -.TP 8 -.B \-s, \-\-msgsize \fI\fP -Message size in bytes -.TP 8 -.B \-m, \-\-mode \fI\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\fP -Show help for \fISUBCOMMAND\fP -.RE -.SS posix info [FLAGS] \fI\fP -Print further information about an existing message queue. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\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\fP -Receive and print one or more messages message from a message queue. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\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\fP -Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S") -.TP 8 -.B \-o, \-\-timeout \fI\fP -Timeout as for example in "5h 23min 42ms" -.RE -.SS posix send [FLAGS] [OPTIONS] \fI\fP \fI\fP -Send a message to a message queue. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\fP -Name of the queue -.TP 8 -.B \fI\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\fP -Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S") -.TP 8 -.B \-p, \-\-priority \fI\fP -Set a different priority than default, priority >= 0 [default: 0] -.TP 8 -.B \-o, \-\-timeout \fI\fP -Timeout as for example in "5h 23min 42ms" -.RE -.SS posix unlink [FLAGS] \fI\fP -Delete an existing POSIX message queue. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\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\fP -Create a new SysV IPC message queue. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\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\fP -Permissions (octal) to create the queue with (default: 0644) -.RE -.SS sysv help [SUBCOMMAND] -Prints this message or the help of the given subcommand. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\fP -Show help for \fISUBCOMMAND\fP -.RE -.SS sysv info [FLAGS] [OPTIONS] -Print further information about an existing message queue. Exactly of -the OPTION arguments is mandatory. -.TP 8 -.SS FLAGS -.RS -.TP 8 -.B \-h, \-\-help -Prints help information -.TP 8 -.B \-v, \-\-verbose -Produce verbose output -.RE -.TP 8 -.SS OPTIONS -.RS -.TP 8 -.B \-i, \-\-id \fI\fP -Id of the queue -.TP 8 -.B \-k, \-\-key \fI\fP -Key of the queue -.RE -.SS sysv list [FLAGS] -Print a list of all existing SysV IPC message queues. -.TP 8 -.SS FLAGS -.RS -.TP 8 -.B \-h, \-\-help -Prints help information -.TP 8 -.B \-v, \-\-verbose -Produce verbose output -.RE -.SS sysv unlink [FLAGS] [OPTIONS] -Delete an existing SysV IPC message queue. It is mandatory to pass -exactly one OPTION. -.TP 8 -.SS ARGS -.RS -.TP 8 -.B \fI\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\fP -Id of the queue -.TP 8 -.B \-k, \-\-key \fI\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) diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..8568937 --- /dev/null +++ b/src/cli.rs @@ -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), +} diff --git a/src/posix/create.rs b/src/create.rs similarity index 60% rename from src/posix/create.rs rename to src/create.rs index cceabde..26652c3 100644 --- a/src/posix/create.rs +++ b/src/create.rs @@ -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, /// 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, - /// 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::().expect("can never fail"), + Ok(m) => m.trim().parse::().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::().expect("can never fail"), + Ok(m) => m.trim().parse::().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(()) diff --git a/src/posix/info.rs b/src/info.rs similarity index 68% rename from src/posix/info.rs rename to src/info.rs index 2a95f6b..e2be5ba 100644 --- a/src/posix/info.rs +++ b/src/info.rs @@ -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(()) diff --git a/src/main.rs b/src/main.rs index c4b0787..e361ffe 100644 --- a/src/main.rs +++ b/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(()) diff --git a/src/posix/list.rs b/src/posix/list.rs deleted file mode 100644 index 57fa45d..0000000 --- a/src/posix/list.rs +++ /dev/null @@ -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 = metadata.modified()?.into(); - let accessed: DateTime = 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(()) - } -} diff --git a/src/posix/mod.rs b/src/posix/mod.rs deleted file mode 100644 index c5855c8..0000000 --- a/src/posix/mod.rs +++ /dev/null @@ -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; diff --git a/src/posix/recv.rs b/src/posix/recv.rs deleted file mode 100644 index c3abb66..0000000 --- a/src/posix/recv.rs +++ /dev/null @@ -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, - /// Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S") - #[clap(short, long, conflicts_with = "timeout")] - deadline: Option, - /// 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::()?)?; - - 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(()) - } -} diff --git a/src/posix/send.rs b/src/posix/send.rs deleted file mode 100644 index 6dd70de..0000000 --- a/src/posix/send.rs +++ /dev/null @@ -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, - /// Deadline until messages are sent (format: "%Y-%m-%d %H:%M:%S") - #[clap(short, long, conflicts_with = "timeout")] - deadline: Option, - /// 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::()?, - )?; - - 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(()) - } -} diff --git a/src/posix/unlink.rs b/src/posix/unlink.rs deleted file mode 100644 index 75a8bd2..0000000 --- a/src/posix/unlink.rs +++ /dev/null @@ -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(()) - } -} diff --git a/src/send.rs b/src/send.rs new file mode 100644 index 0000000..7b8a6e8 --- /dev/null +++ b/src/send.rs @@ -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(()) + } +} diff --git a/src/sysv/create.rs b/src/sysv/create.rs deleted file mode 100644 index 4adad77..0000000 --- a/src/sysv/create.rs +++ /dev/null @@ -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, - /// Key of the new queue - #[clap(value_name = "KEY")] - key: i32, -} - -impl Create { - pub fn run(&self) -> Result<()> { - let mut mq = SysvMq::::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(()) - } -} diff --git a/src/sysv/info.rs b/src/sysv/info.rs deleted file mode 100644 index 77d4b3e..0000000 --- a/src/sysv/info.rs +++ /dev/null @@ -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, - /// Key of the queue - #[clap(short, long, required_unless_present_any = &["id"], conflicts_with = "id")] - key: Option, -} - -fn print_line(line: &str) { - for field in line.split_whitespace().collect::>() { - print!("{0: <10}", field); - } - - println!(); -} - -impl Info { - pub fn run(&self) -> Result<()> { - let mut lines = BufReader::new(File::open("/proc/sysvipc/msg")?).lines(); - - print_line(&lines.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::>()[1].parse::()? { - print_line(&line); - - break; - } - } else if let Some(key) = self.key { - if key == line.split_whitespace().collect::>()[0].parse::()? { - print_line(&line); - - break; - } - } - } - - Ok(()) - } -} diff --git a/src/sysv/list.rs b/src/sysv/list.rs deleted file mode 100644 index 7c12f16..0000000 --- a/src/sysv/list.rs +++ /dev/null @@ -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::>() { - print!("{0: <10}", field); - } - - println!(); - } - - Ok(()) - } -} diff --git a/src/sysv/mod.rs b/src/sysv/mod.rs deleted file mode 100644 index 7270e78..0000000 --- a/src/sysv/mod.rs +++ /dev/null @@ -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; diff --git a/src/sysv/unlink.rs b/src/sysv/unlink.rs deleted file mode 100644 index 9b4b998..0000000 --- a/src/sysv/unlink.rs +++ /dev/null @@ -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, - /// Key of the queue - #[clap(short, long, required_unless_present_any = &["id"], conflicts_with = "id")] - key: Option, -} - -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(()) - } -} diff --git a/src/unlink.rs b/src/unlink.rs new file mode 100644 index 0000000..71eaac4 --- /dev/null +++ b/src/unlink.rs @@ -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(()) + } +} diff --git a/sysvmq/.gitignore b/sysvmq/.gitignore deleted file mode 100644 index 96ef6c0..0000000 --- a/sysvmq/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Cargo.lock diff --git a/sysvmq/Cargo.toml b/sysvmq/Cargo.toml deleted file mode 100644 index a2cee0f..0000000 --- a/sysvmq/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "sysvmq" -version = "0.1.0" -edition = "2018" -authors = ["finga "] -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" diff --git a/sysvmq/src/lib.rs b/sysvmq/src/lib.rs deleted file mode 100644 index 298a48e..0000000 --- a/sysvmq/src/lib.rs +++ /dev/null @@ -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::() as *mut msqid_ds, - ) - }; - - match res { - -1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())), - _ => Ok(()), - } -} - -pub fn id_from_key(key: i32) -> Result { - let id = unsafe { msgget(key, 0) }; - - match id { - -1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())), - id => Ok(id), - } -} - -pub fn ipc_info(id: i32) -> Result<(), SysvMqError> { - let mut msginfo = MaybeUninit::::uninit(); - - unsafe { - msgctl( - id, - ControlCommands::IpcInfo as i32, - msginfo.as_mut_ptr() as *mut msqid_ds, - ); - } - - let msginfo = unsafe { msginfo.assume_init() }; - - println!("info: {:?}", msginfo); - - Ok(()) -} - -pub fn stat_info(id: i32) -> Result<(), SysvMqError> { - let mut msginfo = MaybeUninit::::uninit(); - - unsafe { - msgctl(id, ControlCommands::Stat as i32, msginfo.as_mut_ptr()); - } - - let msginfo = unsafe { msginfo.assume_init() }; - - println!("info: {:?}", msginfo); - - Ok(()) -} - -pub fn msg_info(id: i32) -> Result<(), SysvMqError> { - let mut msginfo = MaybeUninit::::uninit(); - - unsafe { - msgctl( - id, - ControlCommands::MsgInfo as i32, - msginfo.as_mut_ptr() as *mut msqid_ds, - ); - } - - let msginfo = unsafe { msginfo.assume_init() }; - - println!("info: {:?}", msginfo); - - Ok(()) -} - -pub struct SysvMq { - pub id: i32, - pub key: i32, - message_mask: i32, - mode: i32, - types: PhantomData, -} - -impl SysvMq { - 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.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 Default for SysvMq { - fn default() -> Self { - Self::new() - } -}