Skip to content

Instantly share code, notes, and snippets.

@zserge
Created February 18, 2013 14:30
Show Gist options
  • Save zserge/4977827 to your computer and use it in GitHub Desktop.
Save zserge/4977827 to your computer and use it in GitHub Desktop.
diff --git a/lposix.c b/lposix.c
index 03dcbe8..e0bd25c 100644
--- a/lposix.c
+++ b/lposix.c
@@ -34,6 +34,8 @@
#include <time.h>
#include <unistd.h>
#include <utime.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/types.h>
@@ -1322,6 +1324,121 @@ static int Pnanosleep(lua_State *L)
}
/***
+Get a message queue identifier
+@function msgget
+@see msgget(2)
+@int key
+@int flags (optional, default - 0)
+@int mode (optional, default - 0777)
+@return message queue identifier on success
+@return nil and error message if failed
+ */
+static int Pmsgget(lua_State *L)
+{
+ mode_t mode;
+ const char *modestr;
+ key_t key = luaL_checkint(L, 1);
+ int msgflg = luaL_optint(L, 2, 0);
+
+ modestr = luaL_optstring(L, 3,"rwxrwxrwx");
+ if (mode_munch(&mode, modestr)) {
+ luaL_argerror(L, 2, "bad mode");
+ }
+ msgflg |= mode;
+
+ return pushresult(L, msgget(key, msgflg), NULL);
+}
+
+/***
+Send message to a message queue
+@function msgsnd
+@see msgsnd(2)
+@int id - message queue identifier returned by msgget
+@long type - message type
+@string message
+@int flags (optional, default - 0)
+@return 0 on success
+@return nil and error message if failed
+ */
+static int Pmsgsnd(lua_State *L)
+{
+ void *ud;
+ lua_Alloc lalloc;
+ struct {
+ long mtype;
+ char mtext[0];
+ } *msg;
+ size_t len;
+ size_t msgsz;
+ ssize_t res;
+
+ int msgid = luaL_checkint(L, 1);
+ long msgtype = luaL_checklong(L, 2);
+ const char *msgp = luaL_checklstring(L, 3, &len);
+ int msgflg = luaL_optint(L, 4, 0);
+
+ lalloc = lua_getallocf(L, &ud);
+
+ msgsz = sizeof(long) + len;
+
+ if ((msg = lalloc(ud, NULL, 0, msgsz)) == NULL) {
+ return pusherror(L, "lalloc");
+ }
+
+ msg->mtype = msgtype;
+ memcpy(msg->mtext, msgp, len);
+
+ res = msgsnd(msgid, msg, msgsz, msgflg);
+ lua_pushinteger(L, res);
+
+ lalloc(ud, msg, 0, 0);
+
+ return (res == -1 ? pusherror(L, NULL) : 1);
+}
+
+/***
+Receive message from a message queue
+@function msgrcv
+@see msgrcv(2)
+@int id - message queue identifier returned by msgget
+@int size - maximum message size
+@long type - message type (optional, default - 0)
+@int flags (optional, default - 0)
+@return message type and message text on success
+@return nil, nil and error message if failed
+ */
+static int Pmsgrcv(lua_State *L)
+{
+ int msgid = luaL_checkint(L, 1);
+ size_t msgsz = luaL_checkint(L, 2);
+ long msgtyp = luaL_optint(L, 3, 0);
+ int msgflg = luaL_optint(L, 4, 0);
+
+ void *ud;
+ lua_Alloc lalloc;
+ struct {
+ long mtype;
+ char mtext[0];
+ } *msg;
+
+ lalloc = lua_getallocf(L, &ud);
+ if ((msg = lalloc(ud, NULL, 0, msgsz)) == NULL) {
+ return pusherror(L, "lalloc");
+ }
+
+ int res = msgrcv(msgid, msg, msgsz, msgtyp, msgflg);
+ if (res == -1) {
+ lalloc(ud, msg, 0, 0);
+ lua_pushnil(L);
+ return pusherror(L, NULL);
+ }
+ lua_pushinteger(L, msg->mtype);
+ lua_pushlstring(L, msg->mtext, res - sizeof(long));
+
+ return 2;
+}
+
+/***
Set an environment variable for this process.
(Child processes will inherit this)
@function setenv
@@ -3016,6 +3133,9 @@ static const luaL_Reg R[] =
MENTRY( Psignal ),
MENTRY( Psleep ),
MENTRY( Pnanosleep ),
+ MENTRY( Pmsgget ),
+ MENTRY( Pmsgsnd ),
+ MENTRY( Pmsgrcv ),
MENTRY( Pstat ),
MENTRY( Pstrftime ),
MENTRY( Pstrptime ),
@@ -3085,6 +3205,11 @@ LUALIB_API int luaopen_posix_c (lua_State *L)
MENTRY( TRUNC );
#undef MENTRY
+ /* Message queues */
+ set_integer_const( "IPC_CREAT", IPC_CREAT);
+ set_integer_const( "IPC_EXCL", IPC_EXCL);
+ set_integer_const( "IPC_PRIVATE", IPC_PRIVATE);
+
/* Miscellaneous */
set_integer_const( "WNOHANG", WNOHANG );
set_integer_const( "STDIN_FILENO", STDIN_FILENO );
diff --git a/tests-posix.lua b/tests-posix.lua
index 499cbc4..641fd36 100644
--- a/tests-posix.lua
+++ b/tests-posix.lua
@@ -321,4 +321,18 @@ y=ox.timersub(y,{usec=999999})
assert (ox.timercmp(x,y) == 0)
------------------------------------------------------------------------------
+testing"msgget/msgsnd/msgrcv"
+mq, err, errno = ox.msgget(100, bit.bor(ox.IPC_CREAT, ox.IPC_EXCL), "rwxrwxrwx")
+if errno == ox.EEXIST then
+ mq, err = ox.msgget(100, 0, "rwxrwxrwx")
+end
+assert (mq, err)
+a, err = ox.msgsnd(mq, 42, 'Answer to the Ultimate Question of Life')
+assert(a, err)
+mtype, mtext, err = ox.msgrcv(mq, 128)
+assert(mtype == 42)
+assert(mtext == 'Answer to the Ultimate Question of Life')
+assert(err == nil)
+
+------------------------------------------------------------------------------
io.stderr:write("\n\n==== ", ox.version, " tests completed ====\n\n")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment