diff options
Diffstat (limited to 'src/lua-mq.c')
-rw-r--r-- | src/lua-mq.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/lua-mq.c b/src/lua-mq.c new file mode 100644 index 0000000..2975d16 --- /dev/null +++ b/src/lua-mq.c @@ -0,0 +1,179 @@ +#include "lua.h" +#include "lauxlib.h" + +#include <sys/stat.h> +#include <mqueue.h> +#define _XOPEN_SOURCE 600 +#include <errno.h> +#include <string.h> +#include <stdlib.h> + +#define MQD_TYPENAME "mqd_t" +#include "lua-mq.h" + +static mode_t get_mode(const char* modestr) +{ +/* TODO: implement this!!! */ + return S_IRWXU | S_IRWXG; +} + +static int get_oflags(const char* flagstr) +{ + if(!strcmp(flagstr, "ro")) + return O_RDONLY; + + if(!strcmp(flagstr, "wo")) + return O_WRONLY; + + return O_RDWR; +} + +static void push_errno(lua_State *L) +{ + char msg[255]; + int ret; + + ret = strerror_r(errno, msg, sizeof(msg)); + if(!ret) + lua_pushstring(L, msg); + else + lua_pushstring(L, "unknown error"); +} + +static int l_mq_create(lua_State *L) +{ + mqd_t id, *ptr; + int flags; + mode_t mode; + + flags = get_oflags(luaL_optstring(L, 2, "")); + mode = get_mode(luaL_optstring(L, 3, "")); + id = mq_open(luaL_checkstring(L, 1), flags | O_CREAT, mode, NULL); + if(id == (mqd_t)-1) { + lua_pushnil(L); + push_errno(L); + return 2; + } + ptr = (mqd_t*)lua_newuserdata(L, sizeof(mqd_t)); + *ptr = id; + luaL_newmetatable(L, MQD_TYPENAME); + lua_setmetatable(L, -2); + return 1; +} + +static int l_mq_open(lua_State *L) +{ + mqd_t id, *ptr; + int flags; + flags = get_oflags(luaL_optlstring(L, 2, "", NULL)); + id = mq_open(luaL_checkstring(L, 1), flags); + if(id == (mqd_t)-1) { + lua_pushnil(L); + push_errno(L); + return 2; + } + ptr = (mqd_t*)lua_newuserdata(L, sizeof(mqd_t)); + *ptr = id; + luaL_newmetatable(L, MQD_TYPENAME); + lua_setmetatable(L, -2); + return 1; +} + +static int l_mq_send(lua_State *L) +{ + mqd_t* id; + unsigned int prio; + size_t len; + const char* str; + + id = luaL_checkudata(L, 1, MQD_TYPENAME); + str = luaL_checklstring(L, 2, &len); + prio = luaL_optint(L, 3, 0); + if(mq_send(*id, str, len, prio)) { + lua_pushnil(L); + push_errno(L); + return 2; + } + + lua_pushboolean(L, 1); + return 1; +} + +static int l_mq_receive(lua_State *L) +{ + mqd_t* id; + unsigned int prio; + struct mq_attr attr; + ssize_t len; + char* str; + + id = luaL_checkudata(L, 1, MQD_TYPENAME); + if(mq_getattr(*id, &attr)) { + lua_pushnil(L); + push_errno(L); + return 2; + } + + len = attr.mq_msgsize; + str = malloc(len); + if(!str) { + lua_pushnil(L); + lua_pushstring(L, "bad alloc"); + return 2; + } + + len = mq_receive(*id, str, len, &prio); + if(len < 0) { + free(str); + lua_pushnil(L); + push_errno(L); + return 2; + } + + lua_pushlstring(L, str, len); + free(str); + lua_pushinteger(L, prio); + return 2; +} + +static int l_mq_close(lua_State *L) +{ + mqd_t* id; + id = luaL_checkudata(L, 1, MQD_TYPENAME); + if(mq_close(*id)) { + lua_pushnil(L); + push_errno(L); + return 2; + } + + lua_pushboolean(L, 1); + return 1; +} + +static int l_mq_unlink(lua_State *L) +{ + if(mq_unlink(luaL_checkstring(L, 1))) { + lua_pushnil(L); + push_errno(L); + return 2; + } + + lua_pushboolean(L, 1); + return 1; +} + +static const struct luaL_reg mq_funcs [] = { + { "create", l_mq_create }, + { "open", l_mq_open }, + { "send", l_mq_send }, + { "receive", l_mq_receive }, + { "close", l_mq_close }, + { "unlink", l_mq_unlink }, + { NULL, NULL } +}; + +LUALIB_API int luaopen_mq(lua_State *L) +{ + luaL_register(L, "mq", mq_funcs); + return 1; +} |