aboutsummaryrefslogtreecommitdiffstats
path: root/util-src/lsignal.c
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2009-04-12 02:53:50 +0100
committerMatthew Wild <mwild1@gmail.com>2009-04-12 02:53:50 +0100
commit9008dd1e1cc05ce70366054e370a50a9834bccdd (patch)
treee25b85093930ed761424c8f7944d3218a74f07c0 /util-src/lsignal.c
parent23e9b6c71ad350608d617608b4de02709c9b37e1 (diff)
downloadprosody-9008dd1e1cc05ce70366054e370a50a9834bccdd.tar.gz
prosody-9008dd1e1cc05ce70366054e370a50a9834bccdd.zip
util.lsignal: Add lsignal library for catching POSIX signals
Diffstat (limited to 'util-src/lsignal.c')
-rw-r--r--util-src/lsignal.c387
1 files changed, 387 insertions, 0 deletions
diff --git a/util-src/lsignal.c b/util-src/lsignal.c
new file mode 100644
index 00000000..158efcd6
--- /dev/null
+++ b/util-src/lsignal.c
@@ -0,0 +1,387 @@
+/*
+ * lsignal.h -- Signal Handler Library for Lua
+ *
+ * Version: 1.000
+ *
+ * Copyright (C) 2007 Patrick J. Donnelly (batrick@unm.edu)
+ *
+ * This software is distributed under the same license as Lua 5.0:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <signal.h>
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#ifndef lsig
+
+#define lsig
+
+struct lua_signal
+{
+ char *name; /* name of the signal */
+ int sig; /* the signal */
+};
+
+#endif
+
+#define LUA_SIGNAL "lua_signal"
+
+static const struct lua_signal lua_signals[] = {
+ /* ANSI C signals */
+#ifdef SIGABRT
+ {"SIGABRT", SIGABRT},
+#endif
+#ifdef SIGFPE
+ {"SIGFPE", SIGFPE},
+#endif
+#ifdef SIGILL
+ {"SIGILL", SIGILL},
+#endif
+#ifdef SIGINT
+ {"SIGINT", SIGINT},
+#endif
+#ifdef SIGSEGV
+ {"SIGSEGV", SIGSEGV},
+#endif
+#ifdef SIGTERM
+ {"SIGTERM", SIGTERM},
+#endif
+ /* posix signals */
+#ifdef SIGHUP
+ {"SIGHUP", SIGHUP},
+#endif
+#ifdef SIGQUIT
+ {"SIGQUIT", SIGQUIT},
+#endif
+#ifdef SIGTRAP
+ {"SIGTRAP", SIGTRAP},
+#endif
+#ifdef SIGKILL
+ {"SIGKILL", SIGKILL},
+#endif
+#ifdef SIGUSR1
+ {"SIGUSR1", SIGUSR1},
+#endif
+#ifdef SIGUSR2
+ {"SIGUSR2", SIGUSR2},
+#endif
+#ifdef SIGPIPE
+ {"SIGPIPE", SIGPIPE},
+#endif
+#ifdef SIGALRM
+ {"SIGALRM", SIGALRM},
+#endif
+#ifdef SIGCHLD
+ {"SIGCHLD", SIGCHLD},
+#endif
+#ifdef SIGCONT
+ {"SIGCONT", SIGCONT},
+#endif
+#ifdef SIGSTOP
+ {"SIGSTOP", SIGSTOP},
+#endif
+#ifdef SIGTTIN
+ {"SIGTTIN", SIGTTIN},
+#endif
+#ifdef SIGTTOU
+ {"SIGTTOU", SIGTTOU},
+#endif
+ /* some BSD signals */
+#ifdef SIGIOT
+ {"SIGIOT", SIGIOT},
+#endif
+#ifdef SIGBUS
+ {"SIGBUS", SIGBUS},
+#endif
+#ifdef SIGCLD
+ {"SIGCLD", SIGCLD},
+#endif
+#ifdef SIGURG
+ {"SIGURG", SIGURG},
+#endif
+#ifdef SIGXCPU
+ {"SIGXCPU", SIGXCPU},
+#endif
+#ifdef SIGXFSZ
+ {"SIGXFSZ", SIGXFSZ},
+#endif
+#ifdef SIGVTALRM
+ {"SIGVTALRM", SIGVTALRM},
+#endif
+#ifdef SIGPROF
+ {"SIGPROF", SIGPROF},
+#endif
+#ifdef SIGWINCH
+ {"SIGWINCH", SIGWINCH},
+#endif
+#ifdef SIGPOLL
+ {"SIGPOLL", SIGPOLL},
+#endif
+#ifdef SIGIO
+ {"SIGIO", SIGIO},
+#endif
+ /* add odd signals */
+#ifdef SIGSTKFLT
+ {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */
+#endif
+#ifdef SIGSYS
+ {"SIGSYS", SIGSYS},
+#endif
+ {NULL, 0}
+};
+
+static int Nsig = 0;
+static lua_State *Lsig = NULL;
+static lua_Hook Hsig = NULL;
+static int Hmask = 0;
+static int Hcount = 0;
+
+static void sighook(lua_State *L, lua_Debug *ar)
+{
+ lua_pushstring(L, LUA_SIGNAL);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_pushnumber(L, Nsig);
+ lua_gettable(L, -2);
+
+ lua_call(L, 0, 0);
+
+ /* set the old hook */
+ lua_sethook(L, Hsig, Hmask, Hcount);
+}
+
+static void handle(int sig)
+{
+ Hsig = lua_gethook(Lsig);
+ Hmask = lua_gethookmask(Lsig);
+ Hcount = lua_gethookcount(Lsig);
+ Nsig = sig;
+
+ lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
+ /*
+ switch (sig)
+ {
+ case SIGABRT: ;
+ case SIGFPE: ;
+ case SIGILL: ;
+ case SIGINT: ;
+ case SIGSEGV: ;
+ case SIGTERM: ;
+ } */
+}
+
+/*
+ * l_signal == signal(signal [, func [, chook]])
+ *
+ * signal = signal number or string
+ * func = Lua function to call
+ * chook = catch within C functions
+ * if caught, Lua function _must_
+ * exit, as the stack is most likely
+ * in an unstable state.
+*/
+
+static int l_signal(lua_State *L)
+{
+ int args = lua_gettop(L);
+ int t, sig; /* type, signal */
+
+ /* get type of signal */
+ luaL_checkany(L, 1);
+ t = lua_type(L, 1);
+ if (t == LUA_TNUMBER)
+ sig = (int) lua_tonumber(L, 1);
+ else if (t == LUA_TSTRING)
+ {
+ lua_pushstring(L, LUA_SIGNAL);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_pushvalue(L, 1);
+ lua_gettable(L, -2);
+ if (!lua_isnumber(L, -1))
+ luaL_error(L, "invalid signal string");
+ sig = (int) lua_tonumber(L, -1);
+ lua_pop(L, 1); /* get rid of number we pushed */
+ } else
+ luaL_checknumber(L, 1); /* will always error, with good error msg */
+
+ /* set handler */
+ if (args == 1 || lua_isnil(L, 2)) /* clear handler */
+ {
+ lua_pushstring(L, LUA_SIGNAL);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_pushnumber(L, sig);
+ lua_gettable(L, -2); /* return old handler */
+ lua_pushnumber(L, sig);
+ lua_pushnil(L);
+ lua_settable(L, -4);
+ lua_remove(L, -2); /* remove LUA_SIGNAL table */
+ signal(sig, SIG_DFL);
+ } else
+ {
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ lua_pushstring(L, LUA_SIGNAL);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+
+ lua_pushnumber(L, sig);
+ lua_pushvalue(L, 2);
+ lua_settable(L, -3);
+
+ /* Set the state for the handler */
+ Lsig = L;
+
+ if (lua_toboolean(L, 3)) /* c hook? */
+ {
+ if (signal(sig, handle) == SIG_ERR)
+ lua_pushboolean(L, 0);
+ else
+ lua_pushboolean(L, 1);
+ } else /* lua_hook */
+ {
+ if (signal(sig, handle) == SIG_ERR)
+ lua_pushboolean(L, 0);
+ else
+ lua_pushboolean(L, 1);
+ }
+ }
+ return 1;
+}
+
+/*
+ * l_raise == raise(signal)
+ *
+ * signal = signal number or string
+*/
+
+static int l_raise(lua_State *L)
+{
+ /* int args = lua_gettop(L); */
+ int t = 0; /* type */
+ lua_Number ret;
+
+ luaL_checkany(L, 1);
+
+ t = lua_type(L, 1);
+ if (t == LUA_TNUMBER)
+ {
+ ret = (lua_Number) raise((int) lua_tonumber(L, 1));
+ lua_pushnumber(L, ret);
+ } else if (t == LUA_TSTRING)
+ {
+ lua_pushstring(L, LUA_SIGNAL);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_pushvalue(L, 1);
+ lua_gettable(L, -2);
+ if (!lua_isnumber(L, -1))
+ luaL_error(L, "invalid signal string");
+ ret = (lua_Number) raise((int) lua_tonumber(L, -1));
+ lua_pop(L, 1); /* get rid of number we pushed */
+ lua_pushnumber(L, ret);
+ } else
+ luaL_checknumber(L, 1); /* will always error, with good error msg */
+
+ return 1;
+}
+
+#ifdef _POSIX_SOURCE
+
+/* define some posix only functions */
+
+/*
+ * l_kill == kill(pid, signal)
+ *
+ * pid = process id
+ * signal = signal number or string
+*/
+
+static int l_kill(lua_State *L)
+{
+ int t; /* type */
+ lua_Number ret; /* return value */
+
+ luaL_checknumber(L, 1); /* must be int for pid */
+ luaL_checkany(L, 2); /* check for a second arg */
+
+ t = lua_type(L, 2);
+ if (t == LUA_TNUMBER)
+ {
+ ret = (lua_Number) kill((int) lua_tonumber(L, 1),
+ (int) lua_tonumber(L, 2));
+ lua_pushnumber(L, ret);
+ } else if (t == LUA_TSTRING)
+ {
+ lua_pushstring(L, LUA_SIGNAL);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_pushvalue(L, 2);
+ lua_gettable(L, -2);
+ if (!lua_isnumber(L, -1))
+ luaL_error(L, "invalid signal string");
+ ret = (lua_Number) kill((int) lua_tonumber(L, 1),
+ (int) lua_tonumber(L, -1));
+ lua_pop(L, 1); /* get rid of number we pushed */
+ lua_pushnumber(L, ret);
+ } else
+ luaL_checknumber(L, 2); /* will always error, with good error msg */
+ return 1;
+}
+
+#endif
+
+static const struct luaL_Reg lsignal_lib[] = {
+ {"signal", l_signal},
+ {"raise", l_raise},
+#ifdef _POSIX_SOURCE
+ {"kill", l_kill},
+#endif
+ {NULL, NULL}
+};
+
+int luaopen_util_signal(lua_State *L)
+{
+ int i = 0;
+
+ /* add the library */
+ luaL_register(L, "signal", lsignal_lib);
+
+ /* push lua_signals table into the registry */
+ /* put the signals inside the library table too,
+ * they are only a reference */
+ lua_pushstring(L, LUA_SIGNAL);
+ lua_createtable(L, 0, 0);
+
+ while (lua_signals[i].name != NULL)
+ {
+ /* registry table */
+ lua_pushstring(L, lua_signals[i].name);
+ lua_pushnumber(L, lua_signals[i].sig);
+ lua_settable(L, -3);
+ /* signal table */
+ lua_pushstring(L, lua_signals[i].name);
+ lua_pushnumber(L, lua_signals[i].sig);
+ lua_settable(L, -5);
+ i++;
+ }
+
+ /* add newtable to the registry */
+ lua_settable(L, LUA_REGISTRYINDEX);
+
+ return 1;
+}