POSIX IPC is strangely enough painfully missing in the GNU commandline tools.
I really wanted it so I wrote a POSIX IPC implementation for bash (and ofcourse also usable for any other shell scripting language)
Documentation is included as comments in the source below.
More info about POSIX IPC: man mq_overview
(note: mq_open and mq_close are implicit.)
#include <fcntl.h>
#include <limits.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
/* compile with: gcc -Wall -Wextra -o posix_mq posix_mq.c -lrt
* or: tcc -Wall -lrt -o posix_mq posix_mq.c
*
* Create commands:
* ln -s posix_mq mq_send
* ln -s posix_mq mq_receive
* ln -s posix_mq mq_unlink
*
* example:
* mq_send /mytest "hello world"
* mq_receive /mytest
* mq_unlink /mytest
*
* this code is largely based on code written by Peter Hofmann:
* https://www.uninformativ.de/blog/postings/2016-05-16/0/POSTING-en.html
*
* His work, and therefore also this derivative work,
* is published under the following licence:
* -----------------------------------------------------------------------
* "THE PIZZA_WARE LICENCE" (Revision 42):
* This application is largely based on code written by Peter Hofmann
* As long as you retain this notice,
* you can do whatever you want with this stuff. If you meet him some day,
* and you think this stuff is worth it, you can buy him a pizza in return
* -----------------------------------------------------------------------
*
* grtz, tkn (2017)
*/
int main(int argc, char *argv[])
{
mqd_t queue;
struct mq_attr attrs;
char *msg_ptr;
ssize_t recvd;
size_t i, msg_len;
int n;
/* after the last underscore ... */
for( n=strlen(argv[0]) ; n>=0 && argv[0][n]!='_' ; --n );
/* ... get me the first character */
switch(argv[0][++n])
{
case 's':
if (argc < 3)
{
fprintf(stderr, "Usage: %s <queuename> <message>\n", argv[0]);
return 1;
}
queue = mq_open(argv[1], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR, NULL);
if (queue == (mqd_t)-1)
{
perror("mq_open");
return 1;
}
if (mq_getattr(queue, &attrs) == -1)
{
perror("mq_getattr");
mq_close(queue);
return 1;
}
msg_len = strlen(argv[2]);
if (msg_len > LONG_MAX || (long)msg_len > attrs.mq_msgsize)
{
fprintf(stderr, "Your message is too long for the queue.\n");
mq_close(queue);
return 1;
}
if (mq_send(queue, argv[2], strlen(argv[2]), 0) == -1)
{
perror("posix_mq");
mq_close(queue);
return 1;
}
break;
case 'r':
if (argc < 2)
{
fprintf(stderr, "Usage: %s <queuename>\n", argv[0]);
return 1;
}
queue = mq_open(argv[1], O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR, NULL);
if (queue == (mqd_t)-1)
{
perror("mq_open");
return 1;
}
if (mq_getattr(queue, &attrs) == -1)
{
perror("mq_getattr");
mq_close(queue);
return 1;
}
msg_ptr = calloc(1, attrs.mq_msgsize);
if (msg_ptr == NULL)
{
perror("calloc for msg_ptr");
mq_close(queue);
return 1;
}
recvd = mq_receive(queue, msg_ptr, attrs.mq_msgsize, NULL);
if (recvd == -1)
{
perror("mq_receive");
return 1;
}
for (i = 0; i < (size_t)recvd; ++i) putchar(msg_ptr[i]);
printf("\n");
break;
case 'u':
if (argc < 2)
{
fprintf(stderr, "Usage: %s <queuename>\n", argv[0]);
return 1;
}
if ( mq_unlink(argv[1]) )
{
perror("mq_unlink");
return 1;
}
break;
default :
{
fprintf(stderr,
"\nposix_mq implements posix ipc for bash/ash/dash\n\n"
"mq_send /queuename message : send a message to a queue\n"
"mq_receive /queuename : receive a message from a queue\n"
"mq_unlink /queuename : delete a queue\n\n"
"extra info about posix messagequeues: man mq_overview\n\n"
);
return 1;
}
break;
}
return 0;
}