2 * lsignal.h -- Signal Handler Library for Lua
6 * Copyright (C) 2007 Patrick J. Donnelly (batrick@unm.edu)
8 * This software is distributed under the same license as Lua 5.0:
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
40 char *name; /* name of the signal */
41 int sig; /* the signal */
46 #define LUA_SIGNAL "lua_signal"
48 static const struct lua_signal lua_signals[] = {
100 {"SIGSTOP", SIGSTOP},
103 {"SIGTTIN", SIGTTIN},
106 {"SIGTTOU", SIGTTOU},
108 /* some BSD signals */
122 {"SIGXCPU", SIGXCPU},
125 {"SIGXFSZ", SIGXFSZ},
128 {"SIGVTALRM", SIGVTALRM},
131 {"SIGPROF", SIGPROF},
134 {"SIGWINCH", SIGWINCH},
137 {"SIGPOLL", SIGPOLL},
142 /* add odd signals */
144 {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */
153 static lua_State *Lsig = NULL;
154 static lua_Hook Hsig = NULL;
155 static int Hmask = 0;
156 static int Hcount = 0;
158 static void sighook(lua_State *L, lua_Debug *ar)
160 lua_pushstring(L, LUA_SIGNAL);
161 lua_gettable(L, LUA_REGISTRYINDEX);
162 lua_pushnumber(L, Nsig);
167 /* set the old hook */
168 lua_sethook(L, Hsig, Hmask, Hcount);
171 static void handle(int sig)
173 Hsig = lua_gethook(Lsig);
174 Hmask = lua_gethookmask(Lsig);
175 Hcount = lua_gethookcount(Lsig);
178 lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
192 * l_signal == signal(signal [, func [, chook]])
194 * signal = signal number or string
195 * func = Lua function to call
196 * chook = catch within C functions
197 * if caught, Lua function _must_
198 * exit, as the stack is most likely
199 * in an unstable state.
202 static int l_signal(lua_State *L)
204 int args = lua_gettop(L);
205 int t, sig; /* type, signal */
207 /* get type of signal */
210 if (t == LUA_TNUMBER)
211 sig = (int) lua_tonumber(L, 1);
212 else if (t == LUA_TSTRING)
214 lua_pushstring(L, LUA_SIGNAL);
215 lua_gettable(L, LUA_REGISTRYINDEX);
218 if (!lua_isnumber(L, -1))
219 luaL_error(L, "invalid signal string");
220 sig = (int) lua_tonumber(L, -1);
221 lua_pop(L, 1); /* get rid of number we pushed */
223 luaL_checknumber(L, 1); /* will always error, with good error msg */
226 if (args == 1 || lua_isnil(L, 2)) /* clear handler */
228 lua_pushstring(L, LUA_SIGNAL);
229 lua_gettable(L, LUA_REGISTRYINDEX);
230 lua_pushnumber(L, sig);
231 lua_gettable(L, -2); /* return old handler */
232 lua_pushnumber(L, sig);
235 lua_remove(L, -2); /* remove LUA_SIGNAL table */
236 signal(sig, SIG_DFL);
239 luaL_checktype(L, 2, LUA_TFUNCTION);
241 lua_pushstring(L, LUA_SIGNAL);
242 lua_gettable(L, LUA_REGISTRYINDEX);
244 lua_pushnumber(L, sig);
248 /* Set the state for the handler */
251 if (lua_toboolean(L, 3)) /* c hook? */
253 if (signal(sig, handle) == SIG_ERR)
254 lua_pushboolean(L, 0);
256 lua_pushboolean(L, 1);
257 } else /* lua_hook */
259 if (signal(sig, handle) == SIG_ERR)
260 lua_pushboolean(L, 0);
262 lua_pushboolean(L, 1);
269 * l_raise == raise(signal)
271 * signal = signal number or string
274 static int l_raise(lua_State *L)
276 /* int args = lua_gettop(L); */
277 int t = 0; /* type */
283 if (t == LUA_TNUMBER)
285 ret = (lua_Number) raise((int) lua_tonumber(L, 1));
286 lua_pushnumber(L, ret);
287 } else if (t == LUA_TSTRING)
289 lua_pushstring(L, LUA_SIGNAL);
290 lua_gettable(L, LUA_REGISTRYINDEX);
293 if (!lua_isnumber(L, -1))
294 luaL_error(L, "invalid signal string");
295 ret = (lua_Number) raise((int) lua_tonumber(L, -1));
296 lua_pop(L, 1); /* get rid of number we pushed */
297 lua_pushnumber(L, ret);
299 luaL_checknumber(L, 1); /* will always error, with good error msg */
306 /* define some posix only functions */
309 * l_kill == kill(pid, signal)
312 * signal = signal number or string
315 static int l_kill(lua_State *L)
318 lua_Number ret; /* return value */
320 luaL_checknumber(L, 1); /* must be int for pid */
321 luaL_checkany(L, 2); /* check for a second arg */
324 if (t == LUA_TNUMBER)
326 ret = (lua_Number) kill((int) lua_tonumber(L, 1),
327 (int) lua_tonumber(L, 2));
328 lua_pushnumber(L, ret);
329 } else if (t == LUA_TSTRING)
331 lua_pushstring(L, LUA_SIGNAL);
332 lua_gettable(L, LUA_REGISTRYINDEX);
335 if (!lua_isnumber(L, -1))
336 luaL_error(L, "invalid signal string");
337 ret = (lua_Number) kill((int) lua_tonumber(L, 1),
338 (int) lua_tonumber(L, -1));
339 lua_pop(L, 1); /* get rid of number we pushed */
340 lua_pushnumber(L, ret);
342 luaL_checknumber(L, 2); /* will always error, with good error msg */
348 static const struct luaL_Reg lsignal_lib[] = {
349 {"signal", l_signal},
357 int luaopen_util_signal(lua_State *L)
361 /* add the library */
362 luaL_register(L, "signal", lsignal_lib);
364 /* push lua_signals table into the registry */
365 /* put the signals inside the library table too,
366 * they are only a reference */
367 lua_pushstring(L, LUA_SIGNAL);
368 lua_createtable(L, 0, 0);
370 while (lua_signals[i].name != NULL)
373 lua_pushstring(L, lua_signals[i].name);
374 lua_pushnumber(L, lua_signals[i].sig);
377 lua_pushstring(L, lua_signals[i].name);
378 lua_pushnumber(L, lua_signals[i].sig);
383 /* add newtable to the registry */
384 lua_settable(L, LUA_REGISTRYINDEX);