Compare commits

...

22 commits
0.1.1 ... main

Author SHA1 Message Date
finga 8f93d2d6c8 Fix clippy and remove borrows
Fix clippy lints and remove unneded borrows when logging or printing
macros.
2021-12-03 14:57:38 +01:00
finga 1aab989000 Update build dependencies and edition
Use the 2021 Rust edition. To use current version of clap changes were
adapted.
2021-12-03 14:50:23 +01:00
finga d5ef64171a Cargo update and fix clap changes
To support the latest beta version of clap (v3.0.0-beta.4) small
changes were necessary.
2021-10-10 01:23:17 +02:00
finga 8150e30ef5 Update descriptions and manpage
Reflect coping with different message queues.
2021-10-10 01:19:00 +02:00
finga 90a3a5eb52 Use mod files
To have things more self contained.
2021-10-10 01:17:48 +02:00
finga ecd5ee5a36 Add functions to print information about SysV mqs
Not needed yet but maybe useful..
2021-07-09 00:31:51 +02:00
finga 9666e0788d Implement info command for SysV IPC mqs
The `list` command was refactored a little bit as well and the man
page and readme were updated.
2021-07-09 00:29:13 +02:00
finga 4c82d41f8e Implement printing a list of SysV IPC mqs
What could be improved is when printing the information to use a
better human readable format.

As usual the readme and the man page are both updated.
2021-07-08 14:46:10 +02:00
finga f4796e7da6 Refactor sysvmq::unlink_* and check for error
Use `sysvmq::id_from_key(key)` to receive the id of a queue identified
with `key`. Here an error check is added as well. Adapt
`Sysv::Unlink::run()` to comply with that change.
2021-07-08 14:20:53 +02:00
finga 8d127d840e Minor fixes in readme and clap help 2021-07-08 14:14:25 +02:00
finga f726083759 Remove unneccessary pub declarations 2021-07-08 14:13:59 +02:00
finga cc19087195 Implement deletion of SysV IPC message queues
As usual also the readme and the man page are updated.
2021-07-07 20:48:07 +02:00
finga 4d200bb5f3 Implement creation of SysV IPC message queues
This adds the `sysvmq` package which handles SysV IPC message queues.
For consistency the parameter for `permissions` is renamed to `mode`
also for POSIX message queues.
2021-07-07 20:31:16 +02:00
finga a468c5d7bb Move install section into its own file
To keep the readme manageable and clear move help about how to build,
install and run into its own file.
2021-07-07 19:40:14 +02:00
finga 07decf7b36 Add debian package build information in readme
Add prerequisites for building a debian package.
2021-07-07 19:30:18 +02:00
finga 9aae14feae Refactor commands to support different backends
Therefore also the `sysv` backend is intoduced to prepare for future
support. The man page and the readme are updated so far.
2021-07-07 19:19:19 +02:00
finga 4020f062ef Add new subcommand list
Also add it to the readme and manpage.
2021-07-07 18:27:41 +02:00
finga 12b117db7e Refactor logging
To supporte more than a single log level `log` and `env_logger` crates
are used. For the application to support the different type of
argument, the verbose argument definition was adapted.
2021-07-07 17:13:08 +02:00
finga 6a41335603 Cargo update 2021-06-30 22:50:07 +02:00
finga c2ad74ff15 Remove pub declarations and move to posix::*
This is in order to prepare also for SysV message queues.
2021-06-30 22:46:33 +02:00
finga 606b4de524 Use a fn for verbose output when sending 2021-06-27 03:02:45 +02:00
finga f0fb50bc24 Improve help text 2021-06-27 03:02:41 +02:00
21 changed files with 977 additions and 213 deletions

199
Cargo.lock generated
View file

@ -1,10 +1,21 @@
# 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.41"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]]
name = "atty"
@ -29,6 +40,18 @@ 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"
@ -44,9 +67,9 @@ dependencies = [
[[package]]
name = "clap"
version = "3.0.0-beta.2"
version = "3.0.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142"
checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63"
dependencies = [
"atty",
"bitflags",
@ -57,15 +80,14 @@ dependencies = [
"strsim",
"termcolor",
"textwrap",
"unicode-width",
"vec_map",
"unicase",
]
[[package]]
name = "clap_derive"
version = "3.0.0-beta.2"
version = "3.0.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1"
checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3"
dependencies = [
"heck",
"proc-macro-error",
@ -75,10 +97,23 @@ dependencies = [
]
[[package]]
name = "hashbrown"
version = "0.9.1"
name = "env_logger"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
@ -106,9 +141,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "indexmap"
version = "1.6.2"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
@ -122,9 +157,33 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.97"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
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",
]
[[package]]
name = "mqrs"
@ -133,8 +192,24 @@ 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]]
@ -158,9 +233,12 @@ dependencies = [
[[package]]
name = "os_str_bytes"
version = "2.4.0"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799"
dependencies = [
"memchr",
]
[[package]]
name = "posixmq"
@ -197,22 +275,39 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.27"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.9"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
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"
@ -221,15 +316,24 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.73"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "sysvmq"
version = "0.1.0"
dependencies = [
"libc",
"nix",
"thiserror",
]
[[package]]
name = "termcolor"
version = "1.1.2"
@ -241,13 +345,33 @@ dependencies = [
[[package]]
name = "textwrap"
version = "0.12.1"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
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"
@ -260,16 +384,25 @@ dependencies = [
]
[[package]]
name = "unicode-segmentation"
version = "1.7.1"
name = "unicase"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-segmentation"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-width"
version = "0.1.8"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
@ -277,12 +410,6 @@ 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"

View file

@ -2,10 +2,13 @@
name = "mqrs"
version = "0.1.1"
authors = ["finga <mqrs@onders.org>"]
edition = "2018"
edition = "2021"
repository = "https://git.onders.org/finga/mqrs"
license = "GPL-3.0-or-later"
readme = "README.md"
description = "A CLI program for interacting with Posix Message Queues."
description = "A CLI program for interacting with different kinds of message queues."
keywords = ["message_queue", "mq", "mqueue", "queue"]
categories = ["command-line-utilities"]
[dependencies]
anyhow = "1.0"
@ -13,9 +16,15 @@ 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 POSIX message queues."
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"],

49
INSTALL.md Normal file
View file

@ -0,0 +1,49 @@
# 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.

110
README.md
View file

@ -1,81 +1,54 @@
# mqrs
`mqrs` is a small cli application to handle POSIX message queues.
`mqrs` is a small cli application to handle different kinds of message
queues.
## Installation
To build `mqrs` a rust toolchain is necessary.
### 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
```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.
## Install `mqrs`
For information about how to build, install and run `mqrs` please see
[`INSTALL.md`](INSTALL.md).
## Using `mqrs`
`mqrs` supports five commands: `create`, `info`, `unlink`, `send` and
`recv`. All commands do not have to be specified fully. If the
command is clearly distinguishable from all the others, it does not
have to be completed further.
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
### Create a message queue
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
- `-p`, `--permissions`: Permissions (octal) to create the queue with
- `-m`, `--mode`: Permissions (octal) to create the queue with
- `-s`, `--msgsize`: Message size in bytes
### Print information about a message queue
#### Print information about a message queue
Use the `info` command to print further information about a message
queue.
### Delete 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
#### 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>`: Use priority PRIO, PRIO >= 0
[default: 0]
- `-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
#### 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
@ -84,3 +57,28 @@ queue. Following optional arguments are supported:
- `-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

186
mqrs.1
View file

@ -1,37 +1,47 @@
.\" Manpage for mqrs
.TH man 1 "27 June 2021" "0.1.1" "mqrs man page"
.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 POSIX message queues. Supported commands are
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
.
All commands do not have to be specified fully. If the 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
.TP 8
.B \-V, \-\-version
Prints version information
.SH SUBCOMMANDS
.SS create [FLAGS] [OPTIONS] \fI<QUEUE>\fP
.SS posix create [FLAGS] [OPTIONS] \fI<QUEUE>\fP
Create a new POSIX message queue.
.TP 8
.SS ARGS
@ -52,16 +62,17 @@ 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 \-p, \-\-permissions \fI<permissions>\fP
.B \-m, \-\-mode \fI<mode>\fP
Permissions (octal) to create the queue with
.RE
.SS help [SUBCOMMAND]
.SS posix help [SUBCOMMAND]
Prints this message or the help of the given subcommand.
.TP 8
.SS ARGS
@ -70,7 +81,7 @@ Prints this message or the help of the given subcommand.
.B \fI<SUBCOMMAND>\fP
Show help for \fISUBCOMMAND\fP
.RE
.SS info [FLAGS] \fI<QUEUE>\fP
.SS posix info [FLAGS] \fI<QUEUE>\fP
Print further information about an existing message queue.
.TP 8
.SS ARGS
@ -89,7 +100,22 @@ Prints help information
.B \-v, \-\-verbose
Produce verbose output
.RE
.SS recv [FLAGS] [OPTIONS] \fI<QUEUE>\fP
.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
@ -127,7 +153,7 @@ Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
.B \-o, \-\-timeout \fI<timeout>\fP
Timeout as for example in "5h 23min 42ms"
.RE
.SS send [FLAGS] [OPTIONS] \fI<QUEUE>\fP \fI<MESSAGE>\fP
.SS posix send [FLAGS] [OPTIONS] \fI<QUEUE>\fP \fI<MESSAGE>\fP
Send a message to a message queue.
.TP 8
.SS ARGS
@ -160,13 +186,13 @@ Produce verbose output
Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
.TP 8
.B \-p, \-\-priority \fI<priority>\fP
Use priority PRIO, PRIO >= 0 [default: 0]
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 unlink [FLAGS] \fI<QUEUE>\fP
Deletes an existing POSIX message queue.
.SS posix unlink [FLAGS] \fI<QUEUE>\fP
Delete an existing POSIX message queue.
.TP 8
.SS ARGS
.RS
@ -184,8 +210,116 @@ Prints help information
.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)
mq_overview(7), sysvipc(7)
.SH BUGS
No known bugs.
.SH AUTHOR

View file

@ -1,47 +1,82 @@
use crate::{create::Create, info::Info, recv::Recv, send::Send, unlink::Unlink};
use anyhow::Result;
use clap::{crate_authors, crate_version, AppSettings, Clap};
use clap::{crate_authors, crate_version, AppSettings, Parser};
mod create;
mod info;
mod recv;
mod send;
mod unlink;
mod posix;
mod sysv;
#[derive(Clap, Debug)]
#[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::VersionlessSubcommands,
global_setting = AppSettings::PropagateVersion,
global_setting = AppSettings::InferSubcommands,
)]
pub struct Opts {
/// Produce verbose output
#[clap(short, long, global = true)]
pub verbose: bool,
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)]
pub command: Command,
}
#[derive(Clap, Debug)]
pub enum Command {
Create(Create),
Info(Info),
Unlink(Unlink),
Send(Send),
Recv(Recv),
backend: Backend,
}
fn main() -> Result<()> {
let opts: Opts = Opts::parse();
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)?,
Command::Recv(r) => r.run(opts.verbose)?,
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()?,
},
}
Ok(())

View file

@ -1,14 +1,15 @@
use anyhow::Result;
use clap::Clap;
use clap::Parser;
use log::{info, log_enabled, Level::Info};
use posixmq::PosixMq;
use std::fs;
/// Create a POSIX message queue
#[derive(Clap, Debug)]
#[derive(Debug, Parser)]
pub struct Create {
/// Permissions (octal) to create the queue with
#[clap(short, long)]
permissions: Option<String>,
mode: Option<String>,
/// Maximum number of messages in the queue
#[clap(short, long)]
capacity: Option<usize>,
@ -35,11 +36,11 @@ fn msg_default() -> usize {
}
impl Create {
pub fn run(&self, verbose: bool) -> Result<()> {
pub fn run(&self) -> Result<()> {
let mq = &mut posixmq::OpenOptions::readonly();
if let Some(m) = &self.permissions {
mq.mode(u32::from_str_radix(&m, 8)?);
if let Some(m) = &self.mode {
mq.mode(u32::from_str_radix(m, 8)?);
}
mq.max_msg_len(self.msgsize.unwrap_or_else(msgsize_default))
@ -47,15 +48,15 @@ impl Create {
.create_new()
.open(&self.queue)?;
if verbose {
if log_enabled!(Info) {
let mq = PosixMq::open(&self.queue)?;
let attributes = mq.attributes()?;
println!("Created message queue: {} with attributes msgsize: {}, capacity: {}, current_messages: {}",
&self.queue,
&attributes.max_msg_len,
&attributes.capacity,
&attributes.current_messages);
info!("Created message queue: {} with attributes msgsize: {}, capacity: {}, current_messages: {}",
self.queue,
attributes.max_msg_len,
attributes.capacity,
attributes.current_messages);
}
Ok(())

View file

@ -1,13 +1,13 @@
use anyhow::Result;
use clap::Clap;
use clap::Parser;
use posixmq::PosixMq;
/// Print information about an existing message queue
#[derive(Clap, Debug)]
#[derive(Debug, Parser)]
pub struct Info {
/// Name of the queue
#[clap(value_name = "QUEUE")]
pub queue: String,
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(())

58
src/posix/list.rs Normal file
View file

@ -0,0 +1,58 @@
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(())
}
}

13
src/posix/mod.rs Normal file
View file

@ -0,0 +1,13 @@
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;

View file

@ -1,37 +1,36 @@
use anyhow::Result;
use chrono::{DateTime, Local};
use clap::Clap;
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(Clap, Debug)]
#[derive(Debug, Parser)]
pub struct Recv {
/// Do not block
#[clap(short, long)]
pub non_blocking: bool,
non_blocking: bool,
/// Print messages as they are received
#[clap(short, long)]
pub follow: bool,
follow: bool,
/// Print a timestamp before each message
#[clap(short, long)]
pub timestamp: bool,
timestamp: bool,
/// Timeout, example "5h 23min 42ms"
#[clap(short = 'o', long, conflicts_with = "deadline")]
pub timeout: Option<String>,
timeout: Option<String>,
/// Deadline until messages are received (format: "%Y-%m-%d %H:%M:%S")
#[clap(short, long, conflicts_with = "timeout")]
pub deadline: Option<String>,
deadline: Option<String>,
/// Name of the queue
#[clap(value_name = "QUEUE")]
pub queue: String,
queue: String,
}
fn print_message(verbose: bool, priority: u32, length: usize, timestamp: bool, msg: &str) {
if verbose {
println!("Priority: {}, length: {}", priority, length);
}
fn print_message(priority: u32, length: usize, timestamp: bool, msg: &str) {
info!("Priority: {}, length: {}", priority, length);
if timestamp {
println!("{}", Local::now());
@ -41,30 +40,30 @@ fn print_message(verbose: bool, priority: u32, length: usize, timestamp: bool, m
}
impl Recv {
fn receive(&self, verbose: bool, mq: &PosixMq) -> Result<()> {
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(verbose, prio, len, self.timestamp, str::from_utf8(&buf)?);
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(verbose, prio, len, self.timestamp, str::from_utf8(&buf)?);
print_message(prio, len, self.timestamp, str::from_utf8(&buf)?);
} else {
let (prio, len) = mq.recv(&mut buf)?;
print_message(verbose, prio, len, self.timestamp, str::from_utf8(&buf)?);
print_message(prio, len, self.timestamp, str::from_utf8(&buf)?);
}
Ok(())
}
pub fn run(&self, verbose: bool) -> Result<()> {
pub fn run(&self) -> Result<()> {
let mq = &mut posixmq::OpenOptions::readonly();
if self.non_blocking {
@ -75,10 +74,10 @@ impl Recv {
if self.follow {
loop {
self.receive(verbose, &mq)?;
self.receive(&mq)?;
}
} else {
self.receive(verbose, &mq)?;
self.receive(&mq)?;
}
Ok(())

View file

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

View file

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

31
src/sysv/create.rs Normal file
View file

@ -0,0 +1,31 @@
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(())
}
}

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

@ -0,0 +1,53 @@
use anyhow::Result;
use clap::Parser;
use std::{
fs::File,
io::{BufRead, BufReader},
};
/// Print information about an existing message queue
#[derive(Debug, Parser)]
pub struct Info {
/// Id of the queue
#[clap(short, long, required_unless_present_any = &["key"], conflicts_with = "key")]
id: Option<i32>,
/// Key of the queue
#[clap(short, long, required_unless_present_any = &["id"], conflicts_with = "id")]
key: Option<i32>,
}
fn print_line(line: &str) {
for field in line.split_whitespace().collect::<Vec<&str>>() {
print!("{0: <10}", field);
}
println!();
}
impl Info {
pub fn run(&self) -> Result<()> {
let mut lines = BufReader::new(File::open("/proc/sysvipc/msg")?).lines();
print_line(&lines.next().unwrap_or_else(|| Ok(String::new()))?);
for line in lines {
let line = line?;
if let Some(id) = self.id {
if id == line.split_whitespace().collect::<Vec<&str>>()[1].parse::<i32>()? {
print_line(&line);
break;
}
} else if let Some(key) = self.key {
if key == line.split_whitespace().collect::<Vec<&str>>()[0].parse::<i32>()? {
print_line(&line);
break;
}
}
}
Ok(())
}
}

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

@ -0,0 +1,24 @@
use anyhow::Result;
use clap::Parser;
use std::{
fs::File,
io::{BufRead, BufReader},
};
/// Print a list of existing message queues
#[derive(Debug, Parser)]
pub struct List {}
impl List {
pub fn run(&self) -> Result<()> {
for line in BufReader::new(File::open("/proc/sysvipc/msg")?).lines() {
for field in line?.split_whitespace().collect::<Vec<&str>>() {
print!("{0: <10}", field);
}
println!();
}
Ok(())
}
}

9
src/sysv/mod.rs Normal file
View file

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

37
src/sysv/unlink.rs Normal file
View file

@ -0,0 +1,37 @@
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(())
}
}

2
sysvmq/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

12
sysvmq/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[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"

179
sysvmq/src/lib.rs Normal file
View file

@ -0,0 +1,179 @@
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()
}
}