Software /
code /
prosody
Comparison
util-src/signal.c @ 2317:aa58136622bc
util-src/Makefile: Clean up makefile, rename lsignal.c to signal.c
author | Brian Cully <bjc@junctionnetworks.com> |
---|---|
date | Fri, 04 Dec 2009 03:02:25 +0000 |
parent | 1841:util-src/lsignal.c@0dc1daa94e7f |
child | 2343:4b05fd561cbd |
comparison
equal
deleted
inserted
replaced
2316:049cebba35bf | 2317:aa58136622bc |
---|---|
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 } |