From b57d8668ec95eb0a0c84675a7238f89fb1a9d2fd Mon Sep 17 00:00:00 2001
From: Gerhard <Gerhard>
Date: Tue, 18 Feb 2025 12:34:15 +0100
Subject: [PATCH] Added POSIXMQ-WRITE; warn on maxmsg,msgsize failure; doc

---
 CHANGES       |  6 ++++++
 doc/socat.yo  | 13 +++++++------
 xio-posixmq.c | 36 +++++++++++++++++++++++++-----------
 xio-posixmq.h |  1 +
 xioopen.c     |  1 +
 5 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/CHANGES b/CHANGES
index 81a78a4..a563018 100644
--- a/CHANGES
+++ b/CHANGES
@@ -119,6 +119,12 @@ Features:
 	Added generic options setsockopt-socket and setsockopt-connected that
 	are applied after socket() or when connected.
 
+	POSIXMQ addresses now print a warning when options posixmq-maxmsg or
+	posixmq-msgsize were not applied.
+
+	New address POSIXMQ-WRITE does the same as POSIXMQ-SEND, as counterpart
+	of POSIXMQ-READ.
+
 Building:
 	Disabling certain features during configure could break build process.
 
diff --git a/doc/socat.yo b/doc/socat.yo
index 3482e2a..106686a 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -823,6 +823,9 @@ label(ADDRESS_POSIXMQ_SEND)dit(bf(tt(POSIXMQ-SEND:/<mqueue>)))
    link(o-excl)(OPTION_O_EXCL),
    link(umask)(OPTION_UMASK)
 
+label(ADDRESS_POSIXMQ_WRITE)dit(bf(tt(POSIXMQ-WRITE:/<mqueue>)))
+   Does the same as link(POSIXMQ-SEND)(ADDRESS_POSIXMQ_SEND).
+
 label(ADDRESS_POSIXMQ_BIDIRECTIONAL)dit(bf(tt(POSIXMQ-BIDIRECTIONAL:/mqueue)))
 dit(bf(tt(POSIXMQ:/mqueue)))
    Opens or creates the specified POSIX message queue in read and/or write mode
@@ -3522,13 +3525,11 @@ label(OPTION_POSIXMQ_FLUSH)dit(bf(tt(posixmq-flush (mq-flush))))
    "Consumes" (drops) all messages currently in the queue before starting
    transfers.
 label(OPTION_POSIXMQ_MAXMSG)dit(bf(tt(posixmq-maxmsg (mq-maxmsg))))
-   Sets the maxmsg parameter of the POSIX message queue when creating it.
-   Note: You need root or CAP_SYS_RESOURCE to exceed the default value
-   (code(/proc/sys/fs/mqueue/msg_default)).
+   Sets the maxmsg parameter of the POSIX message queue when creating it.nl()
+   Note: This option applies only when the queue does not already exist.
 label(OPTION_POSIXMQ_MSGSIZE)dit(bf(tt(posixmq-msgsize (mq-msgsize))))
-   Sets the msgsize parameter of the POSIX message queue when creating it.
-   Note: You need root or CAP_SYS_RESOURCE to exceed the default value
-   (code(/proc/sys/fs/mqueue/msgsize_default)).
+   Sets the msgsize parameter of the POSIX message queue when creating it.nl()
+   Note: This option applies only when the queue does not already exist.
 enddit()
 
 
diff --git a/xio-posixmq.c b/xio-posixmq.c
index da3bdb3..6fb969f 100644
--- a/xio-posixmq.c
+++ b/xio-posixmq.c
@@ -24,6 +24,7 @@ const struct addrdesc xioaddr_posixmq_bidir   = { "POSIXMQ-BIDIRECTIONAL", 1+XIO
 const struct addrdesc xioaddr_posixmq_read    = { "POSIXMQ-READ",          1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY,                  XIO_RDONLY, 0, 0 HELP(":<mqname>") };
 const struct addrdesc xioaddr_posixmq_receive = { "POSIXMQ-RECEIVE",       1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD,      XIO_RDONLY, XIOREAD_RECV_ONESHOT, 0 HELP(":<mqname>") };
 const struct addrdesc xioaddr_posixmq_send    = { "POSIXMQ-SEND",          1+XIO_WRONLY, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD,      XIO_WRONLY, 0, 0 HELP(":<mqname>") };
+const struct addrdesc xioaddr_posixmq_write   = { "POSIXMQ-WRITE",         1+XIO_WRONLY, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD,      XIO_WRONLY, 0, 0 HELP(":<mqname>") };
 
 const struct optdesc opt_posixmq_priority   = { "posixmq-priority",   "mq-prio",  OPT_POSIXMQ_PRIORITY,   GROUP_POSIXMQ, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.posixmq.prio), XIO_SIZEOF(para.posixmq.prio), 0 };
 const struct optdesc opt_posixmq_flush      = { "posixmq-flush",      "mq-flush", OPT_POSIXMQ_FLUSH,      GROUP_POSIXMQ, PH_EARLY, TYPE_BOOL, OFUNC_SPEC,   0,                               0,                             0 };
@@ -49,6 +50,8 @@ static int xioopen_posixmq(
 	bool opt_unlink_early = false;
 	bool nonblock = 0;
 	bool flush = false;
+	long maxmsg;
+	long msgsize;
 	struct mq_attr attr = { 0 };
 	bool setopts = false;
 	int oflag;
@@ -110,13 +113,13 @@ static int xioopen_posixmq(
 #endif
 	retropt_mode(opts, OPT_PERM,      &opt_mode);
 	retropt_bool(opts, OPT_POSIXMQ_FLUSH, &flush);
-	retropt_long(opts, OPT_POSIXMQ_MAXMSG,  &attr.mq_maxmsg) ||
+	retropt_long(opts, OPT_POSIXMQ_MAXMSG,  &maxmsg) ||
 		(setopts = true);
-	retropt_long(opts, OPT_POSIXMQ_MSGSIZE, &attr.mq_msgsize) ||
+	retropt_long(opts, OPT_POSIXMQ_MSGSIZE, &msgsize) ||
 		(setopts = true);
 
-	/* When only one of mq-maxmsg and mq-msgsize options has been provided,
-	   we must nevertheless set the other option value in strucht mq_attr.
+	/* When just one of mq-maxmsg and mq-msgsize options has been provided,
+	   we must nevertheless set the other option value in struct mq_attr.
 	   For this we have to find the default, read it from /proc fs */
 	if (setopts) {
 		int pfd;
@@ -125,7 +128,7 @@ static int xioopen_posixmq(
 		char buff[21]; 	/* fit a 64bit num in decimal */
 		ssize_t bytes;
 
-		if (attr.mq_maxmsg == 0) {
+		if (maxmsg == 0) {
 			if ((pfd = Open(PROC_MAXMSG, O_RDONLY, 0)) < 0) {
 				Warn2("open(\"%s\", O_RDONLY, 0): %s", PROC_MAXMSG, strerror(errno));
 			} else if ((bytes = Read(pfd, buff, sizeof(buff)-1)) < 0) {
@@ -133,12 +136,12 @@ static int xioopen_posixmq(
 				      pfd, PROC_MAXMSG, sizeof(buff)-1, strerror (errno));
 				Close(pfd);
 			} else {
-				sscanf(buff, "%ld", &attr.mq_maxmsg);
+				sscanf(buff, "%ld", &maxmsg);
 				Close(pfd);
 			}
 		}
 
-		if (attr.mq_msgsize == 0) {
+		if (msgsize == 0) {
 			if ((pfd = Open(PROC_MSGSIZE, O_RDONLY, 0)) < 0) {
 				Warn2("open(\"%s\", O_RDONLY, 0): %s", PROC_MSGSIZE, strerror(errno));
 			} else if ((bytes = Read(pfd, buff, sizeof(buff)-1)) < 0) {
@@ -146,7 +149,7 @@ static int xioopen_posixmq(
 				      pfd, PROC_MSGSIZE, sizeof(buff)-1, strerror (errno));
 				Close(pfd);
 			} else {
-				sscanf(buff, "%ld", &attr.mq_msgsize);
+				sscanf(buff, "%ld", &msgsize);
 				Close(pfd);
 			}
 		}
@@ -181,10 +184,13 @@ static int xioopen_posixmq(
 	}
 
 	/* Now open the message queue */
-	if (setopts)
+	if (setopts) {
+		attr.mq_maxmsg  = maxmsg;
+		attr.mq_msgsize = msgsize;
 		Debug8("%s: mq_open(\"%s\", "F_mode", "F_mode", {flags=%ld, maxmsg=%ld, msgsize=%ld, curmsgs=%ld} )", argv[0], name, oflag, opt_mode, attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
-	else
+	} else {
 		Debug4("%s: mq_open(\"%s\", "F_mode", "F_mode", NULL)", argv[0], name, oflag, opt_mode);
+	}
 	mqd = mq_open(name, oflag, opt_mode, setopts ? &attr : NULL);
 	_errno = errno;
 	Debug1("mq_open() -> %d", mqd);
@@ -206,8 +212,16 @@ static int xioopen_posixmq(
 		mq_close(mqd);
 		return STAT_NORETRY;
 	}
-	Info5("POSIXMQ queue \"%s\": flags=%ld, maxmsg=%ld, msgsize=%ld, curmsgs=%ld",
+	Info5("POSIXMQ queue \"%s\" attrs: { flags=%ld, maxmsg=%ld, msgsize=%ld, curmsgs=%ld }",
 	      name, attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
+	if (setopts) {
+		if (attr.mq_maxmsg != maxmsg)
+			Warn2("mq_open(): requested maxmsg=%ld, but result is %ld",
+			      maxmsg, attr.mq_maxmsg);
+		if (attr.mq_msgsize != msgsize)
+			Warn2("mq_open(): requested msgsize=%ld, but result is %ld",
+			      msgsize, attr.mq_msgsize);
+	}
 
 	if (!dofork && !oneshot) {
 		return STAT_OK;
diff --git a/xio-posixmq.h b/xio-posixmq.h
index 4779f1a..adf827b 100644
--- a/xio-posixmq.h
+++ b/xio-posixmq.h
@@ -9,6 +9,7 @@ extern const struct addrdesc xioaddr_posixmq_bidir;
 extern const struct addrdesc xioaddr_posixmq_read;
 extern const struct addrdesc xioaddr_posixmq_receive;
 extern const struct addrdesc xioaddr_posixmq_send;
+extern const struct addrdesc xioaddr_posixmq_write;
 
 extern const struct optdesc opt_posixmq_maxmsg;
 extern const struct optdesc opt_posixmq_msgsize;
diff --git a/xioopen.c b/xioopen.c
index c83455c..30ec859 100644
--- a/xioopen.c
+++ b/xioopen.c
@@ -183,6 +183,7 @@ const struct addrname addressnames[] = {
    { "POSIXMQ-RECEIVE", 	&xioaddr_posixmq_receive },
    { "POSIXMQ-RECV", 		&xioaddr_posixmq_receive },
    { "POSIXMQ-SEND", 		&xioaddr_posixmq_send },
+   { "POSIXMQ-WRITE", 		&xioaddr_posixmq_write },
 #endif
 #if WITH_PROXY
    { "PROXY",			&xioaddr_proxy_connect },