Created
February 18, 2013 14:30
-
-
Save zserge/4977827 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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