2 -- Copyright (C) 2008-2009 Matthew Wild
3 -- Copyright (C) 2008-2009 Waqas Hussain
4 -- Copyright (C) 2009 Tobias Markmann
6 -- This project is MIT/X11 licensed. Please see the
7 -- COPYING file in the source package for more information.
13 * POSIX support functions for Lua
16 #define MODULE_VERSION "0.3.0"
21 #include <sys/resource.h>
22 #include <sys/types.h>
34 /* Daemonization support */
36 static int lc_daemonize(lua_State *L)
43 lua_pushboolean(L, 0);
44 lua_pushstring(L, "already-daemonized");
48 /* Attempt initial fork */
49 if((pid = fork()) < 0)
52 lua_pushboolean(L, 0);
53 lua_pushstring(L, "fork-failed");
58 /* We are the parent process */
59 lua_pushboolean(L, 1);
60 lua_pushnumber(L, pid);
64 /* and we are the child process */
67 /* We failed to become session leader */
68 /* (we probably already were) */
69 lua_pushboolean(L, 0);
70 lua_pushstring(L, "setsid-failed");
74 /* Close stdin, stdout, stderr */
79 /* Final fork, use it wisely */
83 /* Show's over, let's continue */
84 lua_pushboolean(L, 1);
91 const char * const facility_strings[] = {
113 int facility_constants[] = {
138 The parameter ident in the call of openlog() is probably stored as-is.
139 Thus, if the string it points to is changed, syslog() may start
140 prepending the changed string, and if the string it points to ceases to
141 exist, the results are undefined. Most portable is to use a string
145 char* syslog_ident = NULL;
147 int lc_syslog_open(lua_State* L)
149 int facility = luaL_checkoption(L, 2, "daemon", facility_strings);
150 facility = facility_constants[facility];
152 luaL_checkstring(L, 1);
157 syslog_ident = strdup(lua_tostring(L, 1));
159 openlog(syslog_ident, LOG_PID, facility);
163 const char * const level_strings[] = {
171 int level_constants[] = {
179 int lc_syslog_log(lua_State* L)
181 int level = luaL_checkoption(L, 1, "notice", level_strings);
182 level = level_constants[level];
184 luaL_checkstring(L, 2);
186 syslog(level, "%s", lua_tostring(L, 2));
190 int lc_syslog_close(lua_State* L)
201 int lc_syslog_setmask(lua_State* L)
203 int level_idx = luaL_checkoption(L, 1, "notice", level_strings);
207 mask |= LOG_MASK(level_constants[level_idx]);
208 } while (++level_idx<=4);
216 int lc_getpid(lua_State* L)
218 lua_pushinteger(L, getpid());
222 /* UID/GID functions */
224 int lc_getuid(lua_State* L)
226 lua_pushinteger(L, getuid());
230 int lc_getgid(lua_State* L)
232 lua_pushinteger(L, getgid());
236 int lc_setuid(lua_State* L)
239 if(lua_gettop(L) < 1)
241 if(!lua_isnumber(L, 1) && lua_tostring(L, 1))
243 /* Passed UID is actually a string, so look up the UID */
245 p = getpwnam(lua_tostring(L, 1));
248 lua_pushboolean(L, 0);
249 lua_pushstring(L, "no-such-user");
256 uid = lua_tonumber(L, 1);
261 /* Ok, attempt setuid */
266 lua_pushboolean(L, 0);
270 lua_pushstring(L, "invalid-uid");
273 lua_pushstring(L, "permission-denied");
276 lua_pushstring(L, "unknown-error");
283 lua_pushboolean(L, 1);
288 /* Seems we couldn't find a valid UID to switch to */
289 lua_pushboolean(L, 0);
290 lua_pushstring(L, "invalid-uid");
294 /* Like POSIX's setrlimit()/getrlimit() API functions.
297 * pposix.setrlimit( resource, soft limit, hard limit)
299 * Any negative limit will be replace with the current limit by an additional call of getrlimit().
302 * pposix.setrlimit("NOFILE", 1000, 2000)
304 int string2resource(const char *s) {
305 if (!strcmp(s, "CORE")) return RLIMIT_CORE;
306 if (!strcmp(s, "CPU")) return RLIMIT_CPU;
307 if (!strcmp(s, "DATA")) return RLIMIT_DATA;
308 if (!strcmp(s, "FSIZE")) return RLIMIT_FSIZE;
309 if (!strcmp(s, "MEMLOCK")) return RLIMIT_MEMLOCK;
310 if (!strcmp(s, "NOFILE")) return RLIMIT_NOFILE;
311 if (!strcmp(s, "NPROC")) return RLIMIT_NPROC;
312 if (!strcmp(s, "RSS")) return RLIMIT_RSS;
313 if (!strcmp(s, "STACK")) return RLIMIT_STACK;
317 int lc_setrlimit(lua_State *L) {
318 int arguments = lua_gettop(L);
321 const char *resource = NULL;
323 if(arguments < 1 || arguments > 3) {
324 lua_pushboolean(L, 0);
325 lua_pushstring(L, "incorrect-arguments");
328 resource = luaL_checkstring(L, 1);
329 softlimit = luaL_checkinteger(L, 2);
330 hardlimit = luaL_checkinteger(L, 3);
332 rid = string2resource(resource);
335 struct rlimit lim_current;
337 if (softlimit < 0 || hardlimit < 0) {
338 if (getrlimit(rid, &lim_current)) {
339 lua_pushboolean(L, 0);
340 lua_pushstring(L, "getrlimit-failed");
345 if (softlimit < 0) lim.rlim_cur = lim_current.rlim_cur;
346 else lim.rlim_cur = softlimit;
347 if (hardlimit < 0) lim.rlim_max = lim_current.rlim_max;
348 else lim.rlim_max = hardlimit;
350 if (setrlimit(rid, &lim)) {
351 lua_pushboolean(L, 0);
352 lua_pushstring(L, "setrlimit-failed");
356 /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */
357 lua_pushboolean(L, 0);
358 lua_pushstring(L, "invalid-resource");
361 lua_pushboolean(L, 1);
365 int lc_getrlimit(lua_State *L) {
366 int arguments = lua_gettop(L);
367 const char *resource = NULL;
371 if (arguments != 1) {
372 lua_pushboolean(L, 0);
373 lua_pushstring(L, "invalid-arguments");
377 resource = luaL_checkstring(L, 1);
378 rid = string2resource(resource);
380 if (getrlimit(rid, &lim)) {
381 lua_pushboolean(L, 0);
382 lua_pushstring(L, "getrlimit-failed.");
386 /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */
387 lua_pushboolean(L, 0);
388 lua_pushstring(L, "invalid-resource");
391 lua_pushboolean(L, 1);
392 lua_pushnumber(L, lim.rlim_cur);
393 lua_pushnumber(L, lim.rlim_max);
397 /* Register functions */
399 int luaopen_util_pposix(lua_State *L)
403 lua_pushcfunction(L, lc_daemonize);
404 lua_setfield(L, -2, "daemonize");
406 lua_pushcfunction(L, lc_syslog_open);
407 lua_setfield(L, -2, "syslog_open");
409 lua_pushcfunction(L, lc_syslog_close);
410 lua_setfield(L, -2, "syslog_close");
412 lua_pushcfunction(L, lc_syslog_log);
413 lua_setfield(L, -2, "syslog_log");
415 lua_pushcfunction(L, lc_syslog_setmask);
416 lua_setfield(L, -2, "syslog_setminlevel");
418 lua_pushcfunction(L, lc_getpid);
419 lua_setfield(L, -2, "getpid");
421 lua_pushcfunction(L, lc_getuid);
422 lua_setfield(L, -2, "getuid");
424 lua_pushcfunction(L, lc_setuid);
425 lua_setfield(L, -2, "setuid");
427 lua_pushcfunction(L, lc_setrlimit);
428 lua_setfield(L, -2, "setrlimit");
430 lua_pushcfunction(L, lc_getrlimit);
431 lua_setfield(L, -2, "getrlimit");
433 lua_pushliteral(L, "pposix");
434 lua_setfield(L, -2, "_NAME");
436 lua_pushliteral(L, MODULE_VERSION);
437 lua_setfield(L, -2, "_VERSION");