X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=util-src%2Fpposix.c;h=075c9c8e1b0887881ef5832a16664846c2230730;hb=1b527ae5e85f5dd5e31c240aea8d48c23a56ab25;hp=5e15ed7625a107789412e848540b01bfebe19198;hpb=ec296136d1827b5356fff46784581e6d8706006e;p=prosody.git diff --git a/util-src/pposix.c b/util-src/pposix.c index 5e15ed76..075c9c8e 100644 --- a/util-src/pposix.c +++ b/util-src/pposix.c @@ -1,26 +1,19 @@ -/* Prosody IM v0.1 --- Copyright (C) 2008 Matthew Wild --- Copyright (C) 2008 Waqas Hussain +/* Prosody IM v0.3 +-- Copyright (C) 2008-2009 Matthew Wild +-- Copyright (C) 2008-2009 Waqas Hussain -- --- This program is free software; you can redistribute it and/or --- modify it under the terms of the GNU General Public License --- as published by the Free Software Foundation; either version 2 --- of the License, or (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program; if not, write to the Free Software --- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- */ -/* pposix.c - POSIX support functions for Lua +/* +* pposix.c +* POSIX support functions for Lua */ +#define MODULE_VERSION "0.3.0" + #include #include #include @@ -28,9 +21,17 @@ #include #include +#include +#include + +#include +#include #include "lua.h" +#include "lauxlib.h" + +/* Daemonization support */ -static int daemonize(lua_State *L) +static int lc_daemonize(lua_State *L) { pid_t pid; @@ -83,10 +84,246 @@ static int daemonize(lua_State *L) return 2; } +/* Syslog support */ + +const char * const facility_strings[] = { + "auth", + "authpriv", + "cron", + "daemon", + "ftp", + "kern", + "local0", + "local1", + "local2", + "local3", + "local4", + "local5", + "local6", + "local7", + "lpr", + "mail", + "syslog", + "user", + "uucp", + NULL + }; +int facility_constants[] = { + LOG_AUTH, + LOG_AUTHPRIV, + LOG_CRON, + LOG_DAEMON, + LOG_FTP, + LOG_KERN, + LOG_LOCAL0, + LOG_LOCAL1, + LOG_LOCAL2, + LOG_LOCAL3, + LOG_LOCAL4, + LOG_LOCAL5, + LOG_LOCAL6, + LOG_LOCAL7, + LOG_LPR, + LOG_MAIL, + LOG_NEWS, + LOG_SYSLOG, + LOG_USER, + LOG_UUCP, + -1 + }; + +/* " + The parameter ident in the call of openlog() is probably stored as-is. + Thus, if the string it points to is changed, syslog() may start + prepending the changed string, and if the string it points to ceases to + exist, the results are undefined. Most portable is to use a string + constant. + " -- syslog manpage +*/ +char* syslog_ident = NULL; + +int lc_syslog_open(lua_State* L) +{ + int facility = luaL_checkoption(L, 2, "daemon", facility_strings); + facility = facility_constants[facility]; + + luaL_checkstring(L, 1); + + if(syslog_ident) + free(syslog_ident); + + syslog_ident = strdup(lua_tostring(L, 1)); + + openlog(syslog_ident, LOG_PID, facility); + return 0; +} + +const char * const level_strings[] = { + "debug", + "info", + "notice", + "warn", + "error", + NULL + }; +int level_constants[] = { + LOG_DEBUG, + LOG_INFO, + LOG_NOTICE, + LOG_WARNING, + LOG_EMERG, + -1 + }; +int lc_syslog_log(lua_State* L) +{ + int level = luaL_checkoption(L, 1, "notice", level_strings); + level = level_constants[level]; + + luaL_checkstring(L, 2); + + syslog(level, "%s", lua_tostring(L, 2)); + return 0; +} + +int lc_syslog_close(lua_State* L) +{ + closelog(); + if(syslog_ident) + { + free(syslog_ident); + syslog_ident = NULL; + } + return 0; +} + +int lc_syslog_setmask(lua_State* L) +{ + int level_idx = luaL_checkoption(L, 1, "notice", level_strings); + int mask = 0; + do + { + mask |= LOG_MASK(level_constants[level_idx]); + } while (++level_idx<=4); + + setlogmask(mask); + return 0; +} + +/* getpid */ + +int lc_getpid(lua_State* L) +{ + lua_pushinteger(L, getpid()); + return 1; +} + +/* UID/GID functions */ + +int lc_getuid(lua_State* L) +{ + lua_pushinteger(L, getuid()); + return 1; +} + +int lc_getgid(lua_State* L) +{ + lua_pushinteger(L, getgid()); + return 1; +} + +int lc_setuid(lua_State* L) +{ + int uid = -1; + if(lua_gettop(L) < 1) + return 0; + if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) + { + /* Passed UID is actually a string, so look up the UID */ + struct passwd *p; + p = getpwnam(lua_tostring(L, 1)); + if(!p) + { + lua_pushboolean(L, 0); + lua_pushstring(L, "no-such-user"); + return 2; + } + uid = p->pw_uid; + } + else + { + uid = lua_tonumber(L, 1); + } + + if(uid>-1) + { + /* Ok, attempt setuid */ + errno = 0; + if(setuid(uid)) + { + /* Fail */ + lua_pushboolean(L, 0); + switch(errno) + { + case EINVAL: + lua_pushstring(L, "invalid-uid"); + break; + case EPERM: + lua_pushstring(L, "permission-denied"); + break; + default: + lua_pushstring(L, "unknown-error"); + } + return 2; + } + else + { + /* Success! */ + lua_pushboolean(L, 1); + return 1; + } + } + + /* Seems we couldn't find a valid UID to switch to */ + lua_pushboolean(L, 0); + lua_pushstring(L, "invalid-uid"); + return 2; +} + +/* Register functions */ + int luaopen_util_pposix(lua_State *L) { lua_newtable(L); - lua_pushcfunction(L, daemonize); + + lua_pushcfunction(L, lc_daemonize); lua_setfield(L, -2, "daemonize"); + + lua_pushcfunction(L, lc_syslog_open); + lua_setfield(L, -2, "syslog_open"); + + lua_pushcfunction(L, lc_syslog_close); + lua_setfield(L, -2, "syslog_close"); + + lua_pushcfunction(L, lc_syslog_log); + lua_setfield(L, -2, "syslog_log"); + + lua_pushcfunction(L, lc_syslog_setmask); + lua_setfield(L, -2, "syslog_setminlevel"); + + lua_pushcfunction(L, lc_getpid); + lua_setfield(L, -2, "getpid"); + + lua_pushcfunction(L, lc_getuid); + lua_setfield(L, -2, "getuid"); + + lua_pushcfunction(L, lc_setuid); + lua_setfield(L, -2, "setuid"); + + lua_pushliteral(L, "pposix"); + lua_setfield(L, -2, "_NAME"); + + lua_pushliteral(L, MODULE_VERSION); + lua_setfield(L, -2, "_VERSION"); + return 1; };