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>
35 /* Daemonization support */
37 static int lc_daemonize(lua_State *L)
44 lua_pushboolean(L, 0);
45 lua_pushstring(L, "already-daemonized");
49 /* Attempt initial fork */
50 if((pid = fork()) < 0)
53 lua_pushboolean(L, 0);
54 lua_pushstring(L, "fork-failed");
59 /* We are the parent process */
60 lua_pushboolean(L, 1);
61 lua_pushnumber(L, pid);
65 /* and we are the child process */
68 /* We failed to become session leader */
69 /* (we probably already were) */
70 lua_pushboolean(L, 0);
71 lua_pushstring(L, "setsid-failed");
75 /* Close stdin, stdout, stderr */
80 /* Final fork, use it wisely */
84 /* Show's over, let's continue */
85 lua_pushboolean(L, 1);
92 const char * const facility_strings[] = {
114 int facility_constants[] = {
139 The parameter ident in the call of openlog() is probably stored as-is.
140 Thus, if the string it points to is changed, syslog() may start
141 prepending the changed string, and if the string it points to ceases to
142 exist, the results are undefined. Most portable is to use a string
146 char* syslog_ident = NULL;
148 int lc_syslog_open(lua_State* L)
150 int facility = luaL_checkoption(L, 2, "daemon", facility_strings);
151 facility = facility_constants[facility];
153 luaL_checkstring(L, 1);
158 syslog_ident = strdup(lua_tostring(L, 1));
160 openlog(syslog_ident, LOG_PID, facility);
164 const char * const level_strings[] = {
172 int level_constants[] = {
180 int lc_syslog_log(lua_State* L)
182 int level = luaL_checkoption(L, 1, "notice", level_strings);
183 level = level_constants[level];
185 luaL_checkstring(L, 2);
187 syslog(level, "%s", lua_tostring(L, 2));
191 int lc_syslog_close(lua_State* L)
202 int lc_syslog_setmask(lua_State* L)
204 int level_idx = luaL_checkoption(L, 1, "notice", level_strings);
208 mask |= LOG_MASK(level_constants[level_idx]);
209 } while (++level_idx<=4);
217 int lc_getpid(lua_State* L)
219 lua_pushinteger(L, getpid());
223 /* UID/GID functions */
225 int lc_getuid(lua_State* L)
227 lua_pushinteger(L, getuid());
231 int lc_getgid(lua_State* L)
233 lua_pushinteger(L, getgid());
237 int lc_setuid(lua_State* L)
240 if(lua_gettop(L) < 1)
242 if(!lua_isnumber(L, 1) && lua_tostring(L, 1))
244 /* Passed UID is actually a string, so look up the UID */
246 p = getpwnam(lua_tostring(L, 1));
249 lua_pushboolean(L, 0);
250 lua_pushstring(L, "no-such-user");
257 uid = lua_tonumber(L, 1);
262 /* Ok, attempt setuid */
267 lua_pushboolean(L, 0);
271 lua_pushstring(L, "invalid-uid");
274 lua_pushstring(L, "permission-denied");
277 lua_pushstring(L, "unknown-error");
284 lua_pushboolean(L, 1);
289 /* Seems we couldn't find a valid UID to switch to */
290 lua_pushboolean(L, 0);
291 lua_pushstring(L, "invalid-uid");
295 int lc_setgid(lua_State* L)
298 if(lua_gettop(L) < 1)
300 if(!lua_isnumber(L, 1) && lua_tostring(L, 1))
302 /* Passed GID is actually a string, so look up the GID */
304 g = getgrnam(lua_tostring(L, 1));
307 lua_pushboolean(L, 0);
308 lua_pushstring(L, "no-such-group");
315 gid = lua_tonumber(L, 1);
320 /* Ok, attempt setgid */
325 lua_pushboolean(L, 0);
329 lua_pushstring(L, "invalid-gid");
332 lua_pushstring(L, "permission-denied");
335 lua_pushstring(L, "unknown-error");
342 lua_pushboolean(L, 1);
347 /* Seems we couldn't find a valid GID to switch to */
348 lua_pushboolean(L, 0);
349 lua_pushstring(L, "invalid-gid");
353 /* Like POSIX's setrlimit()/getrlimit() API functions.
356 * pposix.setrlimit( resource, soft limit, hard limit)
358 * Any negative limit will be replace with the current limit by an additional call of getrlimit().
361 * pposix.setrlimit("NOFILE", 1000, 2000)
363 int string2resource(const char *s) {
364 if (!strcmp(s, "CORE")) return RLIMIT_CORE;
365 if (!strcmp(s, "CPU")) return RLIMIT_CPU;
366 if (!strcmp(s, "DATA")) return RLIMIT_DATA;
367 if (!strcmp(s, "FSIZE")) return RLIMIT_FSIZE;
368 if (!strcmp(s, "MEMLOCK")) return RLIMIT_MEMLOCK;
369 if (!strcmp(s, "NOFILE")) return RLIMIT_NOFILE;
370 if (!strcmp(s, "NPROC")) return RLIMIT_NPROC;
371 if (!strcmp(s, "RSS")) return RLIMIT_RSS;
372 if (!strcmp(s, "STACK")) return RLIMIT_STACK;
376 int lc_setrlimit(lua_State *L) {
377 int arguments = lua_gettop(L);
380 const char *resource = NULL;
382 if(arguments < 1 || arguments > 3) {
383 lua_pushboolean(L, 0);
384 lua_pushstring(L, "incorrect-arguments");
387 resource = luaL_checkstring(L, 1);
388 softlimit = luaL_checkinteger(L, 2);
389 hardlimit = luaL_checkinteger(L, 3);
391 rid = string2resource(resource);
394 struct rlimit lim_current;
396 if (softlimit < 0 || hardlimit < 0) {
397 if (getrlimit(rid, &lim_current)) {
398 lua_pushboolean(L, 0);
399 lua_pushstring(L, "getrlimit-failed");
404 if (softlimit < 0) lim.rlim_cur = lim_current.rlim_cur;
405 else lim.rlim_cur = softlimit;
406 if (hardlimit < 0) lim.rlim_max = lim_current.rlim_max;
407 else lim.rlim_max = hardlimit;
409 if (setrlimit(rid, &lim)) {
410 lua_pushboolean(L, 0);
411 lua_pushstring(L, "setrlimit-failed");
415 /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */
416 lua_pushboolean(L, 0);
417 lua_pushstring(L, "invalid-resource");
420 lua_pushboolean(L, 1);
424 int lc_getrlimit(lua_State *L) {
425 int arguments = lua_gettop(L);
426 const char *resource = NULL;
430 if (arguments != 1) {
431 lua_pushboolean(L, 0);
432 lua_pushstring(L, "invalid-arguments");
436 resource = luaL_checkstring(L, 1);
437 rid = string2resource(resource);
439 if (getrlimit(rid, &lim)) {
440 lua_pushboolean(L, 0);
441 lua_pushstring(L, "getrlimit-failed.");
445 /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */
446 lua_pushboolean(L, 0);
447 lua_pushstring(L, "invalid-resource");
450 lua_pushboolean(L, 1);
451 lua_pushnumber(L, lim.rlim_cur);
452 lua_pushnumber(L, lim.rlim_max);
456 /* Register functions */
458 int luaopen_util_pposix(lua_State *L)
462 lua_pushcfunction(L, lc_daemonize);
463 lua_setfield(L, -2, "daemonize");
465 lua_pushcfunction(L, lc_syslog_open);
466 lua_setfield(L, -2, "syslog_open");
468 lua_pushcfunction(L, lc_syslog_close);
469 lua_setfield(L, -2, "syslog_close");
471 lua_pushcfunction(L, lc_syslog_log);
472 lua_setfield(L, -2, "syslog_log");
474 lua_pushcfunction(L, lc_syslog_setmask);
475 lua_setfield(L, -2, "syslog_setminlevel");
477 lua_pushcfunction(L, lc_getpid);
478 lua_setfield(L, -2, "getpid");
480 lua_pushcfunction(L, lc_getuid);
481 lua_setfield(L, -2, "getuid");
482 lua_pushcfunction(L, lc_getgid);
483 lua_setfield(L, -2, "getgid");
485 lua_pushcfunction(L, lc_setuid);
486 lua_setfield(L, -2, "setuid");
487 lua_pushcfunction(L, lc_setgid);
488 lua_setfield(L, -2, "setgid");
490 lua_pushcfunction(L, lc_setrlimit);
491 lua_setfield(L, -2, "setrlimit");
493 lua_pushcfunction(L, lc_getrlimit);
494 lua_setfield(L, -2, "getrlimit");
496 lua_pushliteral(L, "pposix");
497 lua_setfield(L, -2, "_NAME");
499 lua_pushliteral(L, MODULE_VERSION);
500 lua_setfield(L, -2, "_VERSION");