|
1 /* |
|
2 * lsignal.h -- Signal Handler Library for Lua |
|
3 * |
|
4 * Version: 1.000 |
|
5 * |
|
6 * Copyright (C) 2007 Patrick J. Donnelly (batrick@unm.edu) |
|
7 * |
|
8 * This software is distributed under the same license as Lua 5.0: |
|
9 * |
|
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: |
|
16 * |
|
17 * The above copyright notice and this permission notice shall be included |
|
18 * in all copies or substantial portions of the Software. |
|
19 * |
|
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. |
|
27 */ |
|
28 |
|
29 #include <signal.h> |
|
30 |
|
31 #include "lua.h" |
|
32 #include "lauxlib.h" |
|
33 |
|
34 #ifndef lsig |
|
35 |
|
36 #define lsig |
|
37 |
|
38 struct lua_signal |
|
39 { |
|
40 char *name; /* name of the signal */ |
|
41 int sig; /* the signal */ |
|
42 }; |
|
43 |
|
44 #endif |
|
45 |
|
46 #define LUA_SIGNAL "lua_signal" |
|
47 |
|
48 static const struct lua_signal lua_signals[] = { |
|
49 /* ANSI C signals */ |
|
50 #ifdef SIGABRT |
|
51 {"SIGABRT", SIGABRT}, |
|
52 #endif |
|
53 #ifdef SIGFPE |
|
54 {"SIGFPE", SIGFPE}, |
|
55 #endif |
|
56 #ifdef SIGILL |
|
57 {"SIGILL", SIGILL}, |
|
58 #endif |
|
59 #ifdef SIGINT |
|
60 {"SIGINT", SIGINT}, |
|
61 #endif |
|
62 #ifdef SIGSEGV |
|
63 {"SIGSEGV", SIGSEGV}, |
|
64 #endif |
|
65 #ifdef SIGTERM |
|
66 {"SIGTERM", SIGTERM}, |
|
67 #endif |
|
68 /* posix signals */ |
|
69 #ifdef SIGHUP |
|
70 {"SIGHUP", SIGHUP}, |
|
71 #endif |
|
72 #ifdef SIGQUIT |
|
73 {"SIGQUIT", SIGQUIT}, |
|
74 #endif |
|
75 #ifdef SIGTRAP |
|
76 {"SIGTRAP", SIGTRAP}, |
|
77 #endif |
|
78 #ifdef SIGKILL |
|
79 {"SIGKILL", SIGKILL}, |
|
80 #endif |
|
81 #ifdef SIGUSR1 |
|
82 {"SIGUSR1", SIGUSR1}, |
|
83 #endif |
|
84 #ifdef SIGUSR2 |
|
85 {"SIGUSR2", SIGUSR2}, |
|
86 #endif |
|
87 #ifdef SIGPIPE |
|
88 {"SIGPIPE", SIGPIPE}, |
|
89 #endif |
|
90 #ifdef SIGALRM |
|
91 {"SIGALRM", SIGALRM}, |
|
92 #endif |
|
93 #ifdef SIGCHLD |
|
94 {"SIGCHLD", SIGCHLD}, |
|
95 #endif |
|
96 #ifdef SIGCONT |
|
97 {"SIGCONT", SIGCONT}, |
|
98 #endif |
|
99 #ifdef SIGSTOP |
|
100 {"SIGSTOP", SIGSTOP}, |
|
101 #endif |
|
102 #ifdef SIGTTIN |
|
103 {"SIGTTIN", SIGTTIN}, |
|
104 #endif |
|
105 #ifdef SIGTTOU |
|
106 {"SIGTTOU", SIGTTOU}, |
|
107 #endif |
|
108 /* some BSD signals */ |
|
109 #ifdef SIGIOT |
|
110 {"SIGIOT", SIGIOT}, |
|
111 #endif |
|
112 #ifdef SIGBUS |
|
113 {"SIGBUS", SIGBUS}, |
|
114 #endif |
|
115 #ifdef SIGCLD |
|
116 {"SIGCLD", SIGCLD}, |
|
117 #endif |
|
118 #ifdef SIGURG |
|
119 {"SIGURG", SIGURG}, |
|
120 #endif |
|
121 #ifdef SIGXCPU |
|
122 {"SIGXCPU", SIGXCPU}, |
|
123 #endif |
|
124 #ifdef SIGXFSZ |
|
125 {"SIGXFSZ", SIGXFSZ}, |
|
126 #endif |
|
127 #ifdef SIGVTALRM |
|
128 {"SIGVTALRM", SIGVTALRM}, |
|
129 #endif |
|
130 #ifdef SIGPROF |
|
131 {"SIGPROF", SIGPROF}, |
|
132 #endif |
|
133 #ifdef SIGWINCH |
|
134 {"SIGWINCH", SIGWINCH}, |
|
135 #endif |
|
136 #ifdef SIGPOLL |
|
137 {"SIGPOLL", SIGPOLL}, |
|
138 #endif |
|
139 #ifdef SIGIO |
|
140 {"SIGIO", SIGIO}, |
|
141 #endif |
|
142 /* add odd signals */ |
|
143 #ifdef SIGSTKFLT |
|
144 {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */ |
|
145 #endif |
|
146 #ifdef SIGSYS |
|
147 {"SIGSYS", SIGSYS}, |
|
148 #endif |
|
149 {NULL, 0} |
|
150 }; |
|
151 |
|
152 static int Nsig = 0; |
|
153 static lua_State *Lsig = NULL; |
|
154 static lua_Hook Hsig = NULL; |
|
155 static int Hmask = 0; |
|
156 static int Hcount = 0; |
|
157 |
|
158 static void sighook(lua_State *L, lua_Debug *ar) |
|
159 { |
|
160 lua_pushstring(L, LUA_SIGNAL); |
|
161 lua_gettable(L, LUA_REGISTRYINDEX); |
|
162 lua_pushnumber(L, Nsig); |
|
163 lua_gettable(L, -2); |
|
164 |
|
165 lua_call(L, 0, 0); |
|
166 |
|
167 /* set the old hook */ |
|
168 lua_sethook(L, Hsig, Hmask, Hcount); |
|
169 } |
|
170 |
|
171 static void handle(int sig) |
|
172 { |
|
173 Hsig = lua_gethook(Lsig); |
|
174 Hmask = lua_gethookmask(Lsig); |
|
175 Hcount = lua_gethookcount(Lsig); |
|
176 Nsig = sig; |
|
177 |
|
178 lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); |
|
179 /* |
|
180 switch (sig) |
|
181 { |
|
182 case SIGABRT: ; |
|
183 case SIGFPE: ; |
|
184 case SIGILL: ; |
|
185 case SIGINT: ; |
|
186 case SIGSEGV: ; |
|
187 case SIGTERM: ; |
|
188 } */ |
|
189 } |
|
190 |
|
191 /* |
|
192 * l_signal == signal(signal [, func [, chook]]) |
|
193 * |
|
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. |
|
200 */ |
|
201 |
|
202 static int l_signal(lua_State *L) |
|
203 { |
|
204 int args = lua_gettop(L); |
|
205 int t, sig; /* type, signal */ |
|
206 |
|
207 /* get type of signal */ |
|
208 luaL_checkany(L, 1); |
|
209 t = lua_type(L, 1); |
|
210 if (t == LUA_TNUMBER) |
|
211 sig = (int) lua_tonumber(L, 1); |
|
212 else if (t == LUA_TSTRING) |
|
213 { |
|
214 lua_pushstring(L, LUA_SIGNAL); |
|
215 lua_gettable(L, LUA_REGISTRYINDEX); |
|
216 lua_pushvalue(L, 1); |
|
217 lua_gettable(L, -2); |
|
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 */ |
|
222 } else |
|
223 luaL_checknumber(L, 1); /* will always error, with good error msg */ |
|
224 |
|
225 /* set handler */ |
|
226 if (args == 1 || lua_isnil(L, 2)) /* clear handler */ |
|
227 { |
|
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); |
|
233 lua_pushnil(L); |
|
234 lua_settable(L, -4); |
|
235 lua_remove(L, -2); /* remove LUA_SIGNAL table */ |
|
236 signal(sig, SIG_DFL); |
|
237 } else |
|
238 { |
|
239 luaL_checktype(L, 2, LUA_TFUNCTION); |
|
240 |
|
241 lua_pushstring(L, LUA_SIGNAL); |
|
242 lua_gettable(L, LUA_REGISTRYINDEX); |
|
243 |
|
244 lua_pushnumber(L, sig); |
|
245 lua_pushvalue(L, 2); |
|
246 lua_settable(L, -3); |
|
247 |
|
248 /* Set the state for the handler */ |
|
249 Lsig = L; |
|
250 |
|
251 if (lua_toboolean(L, 3)) /* c hook? */ |
|
252 { |
|
253 if (signal(sig, handle) == SIG_ERR) |
|
254 lua_pushboolean(L, 0); |
|
255 else |
|
256 lua_pushboolean(L, 1); |
|
257 } else /* lua_hook */ |
|
258 { |
|
259 if (signal(sig, handle) == SIG_ERR) |
|
260 lua_pushboolean(L, 0); |
|
261 else |
|
262 lua_pushboolean(L, 1); |
|
263 } |
|
264 } |
|
265 return 1; |
|
266 } |
|
267 |
|
268 /* |
|
269 * l_raise == raise(signal) |
|
270 * |
|
271 * signal = signal number or string |
|
272 */ |
|
273 |
|
274 static int l_raise(lua_State *L) |
|
275 { |
|
276 /* int args = lua_gettop(L); */ |
|
277 int t = 0; /* type */ |
|
278 lua_Number ret; |
|
279 |
|
280 luaL_checkany(L, 1); |
|
281 |
|
282 t = lua_type(L, 1); |
|
283 if (t == LUA_TNUMBER) |
|
284 { |
|
285 ret = (lua_Number) raise((int) lua_tonumber(L, 1)); |
|
286 lua_pushnumber(L, ret); |
|
287 } else if (t == LUA_TSTRING) |
|
288 { |
|
289 lua_pushstring(L, LUA_SIGNAL); |
|
290 lua_gettable(L, LUA_REGISTRYINDEX); |
|
291 lua_pushvalue(L, 1); |
|
292 lua_gettable(L, -2); |
|
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); |
|
298 } else |
|
299 luaL_checknumber(L, 1); /* will always error, with good error msg */ |
|
300 |
|
301 return 1; |
|
302 } |
|
303 |
|
304 #if defined _POSIX_SOURCE || (defined(sun) || defined(__sun)) |
|
305 |
|
306 /* define some posix only functions */ |
|
307 |
|
308 /* |
|
309 * l_kill == kill(pid, signal) |
|
310 * |
|
311 * pid = process id |
|
312 * signal = signal number or string |
|
313 */ |
|
314 |
|
315 static int l_kill(lua_State *L) |
|
316 { |
|
317 int t; /* type */ |
|
318 lua_Number ret; /* return value */ |
|
319 |
|
320 luaL_checknumber(L, 1); /* must be int for pid */ |
|
321 luaL_checkany(L, 2); /* check for a second arg */ |
|
322 |
|
323 t = lua_type(L, 2); |
|
324 if (t == LUA_TNUMBER) |
|
325 { |
|
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) |
|
330 { |
|
331 lua_pushstring(L, LUA_SIGNAL); |
|
332 lua_gettable(L, LUA_REGISTRYINDEX); |
|
333 lua_pushvalue(L, 2); |
|
334 lua_gettable(L, -2); |
|
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); |
|
341 } else |
|
342 luaL_checknumber(L, 2); /* will always error, with good error msg */ |
|
343 return 1; |
|
344 } |
|
345 |
|
346 #endif |
|
347 |
|
348 static const struct luaL_Reg lsignal_lib[] = { |
|
349 {"signal", l_signal}, |
|
350 {"raise", l_raise}, |
|
351 #ifdef _POSIX_SOURCE |
|
352 {"kill", l_kill}, |
|
353 #endif |
|
354 {NULL, NULL} |
|
355 }; |
|
356 |
|
357 int luaopen_util_signal(lua_State *L) |
|
358 { |
|
359 int i = 0; |
|
360 |
|
361 /* add the library */ |
|
362 luaL_register(L, "signal", lsignal_lib); |
|
363 |
|
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); |
|
369 |
|
370 while (lua_signals[i].name != NULL) |
|
371 { |
|
372 /* registry table */ |
|
373 lua_pushstring(L, lua_signals[i].name); |
|
374 lua_pushnumber(L, lua_signals[i].sig); |
|
375 lua_settable(L, -3); |
|
376 /* signal table */ |
|
377 lua_pushstring(L, lua_signals[i].name); |
|
378 lua_pushnumber(L, lua_signals[i].sig); |
|
379 lua_settable(L, -5); |
|
380 i++; |
|
381 } |
|
382 |
|
383 /* add newtable to the registry */ |
|
384 lua_settable(L, LUA_REGISTRYINDEX); |
|
385 |
|
386 return 1; |
|
387 } |