Blame ext/posix/sys/msg.c

Packit 437b5e
/*
Packit 437b5e
 * POSIX library for Lua 5.1, 5.2 & 5.3.
Packit 437b5e
 * (c) Gary V. Vaughan <gary@vaughan.pe>, 2013-2015
Packit 437b5e
 * (c) Reuben Thomas <rrt@sc3d.org> 2010-2013
Packit 437b5e
 * (c) Natanael Copa <natanael.copa@gmail.com> 2008-2010
Packit 437b5e
 * Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11
Packit 437b5e
 * Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> 07 Apr 2006 23:17:49
Packit 437b5e
 * Based on original by Claudio Terra for Lua 3.x.
Packit 437b5e
 * With contributions by Roberto Ierusalimschy.
Packit 437b5e
 * With documentation from Steve Donovan 2012
Packit 437b5e
 */
Packit 437b5e
/***
Packit 437b5e
 Sys V Message Queue Operations.
Packit 437b5e
Packit 437b5e
 Where supported by the underlying system, functions to send and receive
Packit 437b5e
 interprocess messages.  If the module loads successfully, but there is
Packit 437b5e
 no system support, then `posix.sys.msg.version` will be set, but the
Packit 437b5e
 unsupported APIs wil be `nil`.
Packit 437b5e
Packit 437b5e
@module posix.sys.msg
Packit 437b5e
*/
Packit 437b5e
Packit 437b5e
#include <config.h>
Packit 437b5e
Packit 437b5e
#include "_helpers.c"	/* For LPOSIX_2001_COMPLIANT */
Packit 437b5e
Packit 437b5e
#if HAVE_SYSV_MESSAGING
Packit 437b5e
#include <sys/ipc.h>
Packit 437b5e
#include <sys/msg.h>
Packit 437b5e
#include <sys/types.h>
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Get a message queue identifier
Packit 437b5e
@function msgget
Packit 437b5e
@int key message queue id, or `IPC_PRIVATE` for a new queue
Packit 437b5e
@int[opt=0] flags bitwise OR of zero or more from `IPC_CREAT` and `IPC_EXCL`,
Packit 437b5e
  and access permissions `S_IRUSR`, `S_IWUSR`, `S_IRGRP`, `S_IWGRP`, `S_IROTH`
Packit 437b5e
  and `S_IWOTH` (from @{posix.sys.stat})
Packit 437b5e
@treturn[1] int message queue identifier, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see msgget(2)
Packit 437b5e
*/
Packit 437b5e
static int
Packit 437b5e
Pmsgget(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	checknargs (L, 2);
Packit 437b5e
	return pushresult(L, msgget(checkint(L, 1), optint(L, 2, 0)), "msgget");
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Send message to a message queue
Packit 437b5e
@function msgsnd
Packit 437b5e
@int id message queue identifier returned by @{msgget}
Packit 437b5e
@int type arbitrary message type
Packit 437b5e
@string message content
Packit 437b5e
@int[opt=0] flags optionally `IPC_NOWAIT`
Packit 437b5e
@treturn int 0, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see msgsnd(2)
Packit 437b5e
 */
Packit 437b5e
static int
Packit 437b5e
Pmsgsnd(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	void *ud;
Packit 437b5e
	lua_Alloc lalloc = lua_getallocf(L, &ud);
Packit 437b5e
	struct {
Packit 437b5e
		long mtype;
Packit 437b5e
		char mtext[0];
Packit 437b5e
	} *msg;
Packit 437b5e
	size_t len;
Packit 437b5e
	size_t msgsz;
Packit 437b5e
	ssize_t r;
Packit 437b5e
Packit 437b5e
	int msgid = checkint(L, 1);
Packit 437b5e
	long msgtype = checklong(L, 2);
Packit 437b5e
	const char *msgp = luaL_checklstring(L, 3, &len;;
Packit 437b5e
	int msgflg = optint(L, 4, 0);
Packit 437b5e
Packit 437b5e
	checknargs(L, 4);
Packit 437b5e
Packit 437b5e
	msgsz = sizeof(long) + len;
Packit 437b5e
Packit 437b5e
	if ((msg = lalloc(ud, NULL, 0, msgsz)) == NULL)
Packit 437b5e
		return pusherror(L, "lalloc");
Packit 437b5e
Packit 437b5e
	msg->mtype = msgtype;
Packit 437b5e
	memcpy(msg->mtext, msgp, len);
Packit 437b5e
Packit 437b5e
	r = msgsnd(msgid, msg, msgsz, msgflg);
Packit 437b5e
	lua_pushinteger(L, r);
Packit 437b5e
Packit 437b5e
	lalloc(ud, msg, msgsz, 0);
Packit 437b5e
Packit 437b5e
	return (r == -1 ? pusherror(L, NULL) : 1);
Packit 437b5e
}
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Receive message from a message queue
Packit 437b5e
@function msgrcv
Packit 437b5e
@int id message queue identifier returned by @{msgget}
Packit 437b5e
@int size maximum message size
Packit 437b5e
@int type message type (optional, default - 0)
Packit 437b5e
@int[opt=0] flags bitwise OR of zero or more of `IPC_NOWAIT`, `MSG_EXCEPT`
Packit 437b5e
  and `MSG_NOERROR`
Packit 437b5e
@treturn[1] int message type from @{msgsnd}
Packit 437b5e
@treturn[1] string message text, if successful
Packit 437b5e
@return[2] nil
Packit 437b5e
@treturn[2] string error message
Packit 437b5e
@treturn[2] int errnum
Packit 437b5e
@see msgrcv(2)
Packit 437b5e
 */
Packit 437b5e
static int
Packit 437b5e
Pmsgrcv(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	int msgid = checkint(L, 1);
Packit 437b5e
	size_t msgsz = checkint(L, 2);
Packit 437b5e
	long msgtyp = optint(L, 3, 0);
Packit 437b5e
	int msgflg = optint(L, 4, 0);
Packit 437b5e
Packit 437b5e
	void *ud;
Packit 437b5e
	lua_Alloc lalloc;
Packit 437b5e
	struct {
Packit 437b5e
		long mtype;
Packit 437b5e
		char mtext[0];
Packit 437b5e
	} *msg;
Packit 437b5e
Packit 437b5e
	checknargs(L, 4);
Packit 437b5e
	lalloc = lua_getallocf(L, &ud);
Packit 437b5e
Packit 437b5e
	if ((msg = lalloc(ud, NULL, 0, msgsz)) == NULL)
Packit 437b5e
		return pusherror(L, "lalloc");
Packit 437b5e
Packit 437b5e
	int res = msgrcv(msgid, msg, msgsz, msgtyp, msgflg);
Packit 437b5e
	if (res != -1)
Packit 437b5e
	{
Packit 437b5e
		lua_pushinteger(L, msg->mtype);
Packit 437b5e
		lua_pushlstring(L, msg->mtext, res - sizeof(long));
Packit 437b5e
	}
Packit 437b5e
	lalloc(ud, msg, msgsz, 0);
Packit 437b5e
Packit 437b5e
	return (res == -1) ? pusherror(L, NULL) : 2;
Packit 437b5e
}
Packit 437b5e
#endif /*!HAVE_SYSV_MESSAGING*/
Packit 437b5e
Packit 437b5e
Packit 437b5e
static const luaL_Reg posix_sys_msg_fns[] =
Packit 437b5e
{
Packit 437b5e
#if HAVE_SYSV_MESSAGING
Packit 437b5e
	LPOSIX_FUNC( Pmsgget		),
Packit 437b5e
	LPOSIX_FUNC( Pmsgsnd		),
Packit 437b5e
	LPOSIX_FUNC( Pmsgrcv		),
Packit 437b5e
#endif
Packit 437b5e
	{NULL, NULL}
Packit 437b5e
};
Packit 437b5e
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Constants.
Packit 437b5e
@section constants
Packit 437b5e
*/
Packit 437b5e
Packit 437b5e
/***
Packit 437b5e
Message constants.
Packit 437b5e
Any constants not available in the underlying system will be `nil` valued.
Packit 437b5e
@table posix.sys.msg
Packit 437b5e
@int IPC_CREAT create entry if key does not exist
Packit 437b5e
@int IPC_EXCL fail if key exists
Packit 437b5e
@int IPC_PRIVATE private key
Packit 437b5e
@int IPC_NOWAIT error if request must wait
Packit 437b5e
@int MSG_EXCEPT read messages with differing type
Packit 437b5e
@int MSG_NOERROR truncate received message rather than erroring
Packit 437b5e
@usage
Packit 437b5e
  -- Print msg constants supported on this host.
Packit 437b5e
  for name, value in pairs (require "posix.sys.msg") do
Packit 437b5e
    if type (value) == "number" then
Packit 437b5e
      print (name, value)
Packit 437b5e
     end
Packit 437b5e
  end
Packit 437b5e
*/
Packit 437b5e
Packit 437b5e
LUALIB_API int
Packit 437b5e
luaopen_posix_sys_msg(lua_State *L)
Packit 437b5e
{
Packit 437b5e
	luaL_register(L, "posix.sys.msg", posix_sys_msg_fns);
Packit 437b5e
	lua_pushliteral(L, "posix.sys.msg for " LUA_VERSION " / " PACKAGE_STRING);
Packit 437b5e
	lua_setfield(L, -2, "version");
Packit 437b5e
Packit 437b5e
#if HAVE_SYSV_MESSAGING
Packit 437b5e
	LPOSIX_CONST( IPC_CREAT		);
Packit 437b5e
	LPOSIX_CONST( IPC_EXCL		);
Packit 437b5e
	LPOSIX_CONST( IPC_PRIVATE	);
Packit 437b5e
	LPOSIX_CONST( IPC_NOWAIT	);
Packit 437b5e
#  ifdef MSG_EXCEPT
Packit 437b5e
	LPOSIX_CONST( MSG_EXCEPT	);
Packit 437b5e
#  endif
Packit 437b5e
#  ifdef MSG_NOERROR
Packit 437b5e
	LPOSIX_CONST( MSG_NOERROR	);
Packit 437b5e
#  endif
Packit 437b5e
#endif
Packit 437b5e
Packit 437b5e
	return 1;
Packit 437b5e
}