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, "Wrong number of 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 lua_pushboolean(L, 0);
357 lua_pushstring(L, "Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard.");
360 lua_pushboolean(L, 1);
364 int lc_getrlimit(lua_State *L) {
365 int arguments = lua_gettop(L);
366 const char *resource = NULL;
370 if (arguments != 1) {
371 lua_pushboolean(L, 0);
372 lua_pushstring(L, "I expect one argument only, the resource string.");
376 resource = luaL_checkstring(L, 1);
377 rid = string2resource(resource);
379 if (getrlimit(rid, &lim)) {
380 lua_pushboolean(L, 0);
381 lua_pushstring(L, "getrlimit() failed.");
385 lua_pushboolean(L, 0);
386 lua_pushstring(L, "Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard.");
389 lua_pushboolean(L, 1);
390 lua_pushnumber(L, lim.rlim_cur);
391 lua_pushnumber(L, lim.rlim_max);
395 /* Register functions */
397 int luaopen_util_pposix(lua_State *L)
401 lua_pushcfunction(L, lc_daemonize);
402 lua_setfield(L, -2, "daemonize");
404 lua_pushcfunction(L, lc_syslog_open);
405 lua_setfield(L, -2, "syslog_open");
407 lua_pushcfunction(L, lc_syslog_close);
408 lua_setfield(L, -2, "syslog_close");
410 lua_pushcfunction(L, lc_syslog_log);
411 lua_setfield(L, -2, "syslog_log");
413 lua_pushcfunction(L, lc_syslog_setmask);
414 lua_setfield(L, -2, "syslog_setminlevel");
416 lua_pushcfunction(L, lc_getpid);
417 lua_setfield(L, -2, "getpid");
419 lua_pushcfunction(L, lc_getuid);
420 lua_setfield(L, -2, "getuid");
422 lua_pushcfunction(L, lc_setuid);
423 lua_setfield(L, -2, "setuid");
425 lua_pushcfunction(L, lc_setrlimit);
426 lua_setfield(L, -2, "setrlimit");
428 lua_pushcfunction(L, lc_getrlimit);
429 lua_setfield(L, -2, "getrlimit");
431 lua_pushliteral(L, "pposix");
432 lua_setfield(L, -2, "_NAME");
434 lua_pushliteral(L, MODULE_VERSION);
435 lua_setfield(L, -2, "_VERSION");