core.modulemanager: Some refactoring to make upcoming changes a little easier
[prosody.git] / util-src / pposix.c
1 /* Prosody IM v0.1
2 -- Copyright (C) 2008 Matthew Wild
3 -- Copyright (C) 2008 Waqas Hussain
4 -- 
5 -- This program is free software; you can redistribute it and/or
6 -- modify it under the terms of the GNU General Public License
7 -- as published by the Free Software Foundation; either version 2
8 -- of the License, or (at your option) any later version.
9 -- 
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 -- GNU General Public License for more details.
14 -- 
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 */
19
20 /* pposix.c
21    POSIX support functions for Lua
22 */
23
24 #define MODULE_VERSION "0.3.0"
25
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <libgen.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32
33 #include <syslog.h>
34
35 #include <string.h>
36
37 #include "lua.h"
38 #include "lauxlib.h"
39
40 /* Daemonization support */
41
42 static int lc_daemonize(lua_State *L)
43 {
44
45         pid_t pid;
46         
47         if ( getppid() == 1 )
48         {
49                 lua_pushboolean(L, 0);
50                 lua_pushstring(L, "already-daemonized");
51                 return 2;
52         }
53         
54         /* Attempt initial fork */
55         if((pid = fork()) < 0)
56         {
57                 /* Forking failed */
58                 lua_pushboolean(L, 0);
59                 lua_pushstring(L, "fork-failed");
60                 return 2;
61         }
62         else if(pid != 0)
63         {
64                 /* We are the parent process */
65                 lua_pushboolean(L, 1);
66                 lua_pushnumber(L, pid);
67                 return 2;
68         }
69         
70         /* and we are the child process */
71         if(setsid() == -1)
72         {
73                 /* We failed to become session leader */
74                 /* (we probably already were) */
75                 lua_pushboolean(L, 0);
76                 lua_pushstring(L, "setsid-failed");
77                 return 2;
78         }
79
80         /* Close stdin, stdout, stderr */
81 /*      close(0);
82         close(1);
83         close(2);
84 */
85         /* Final fork, use it wisely */
86         if(fork())
87                 exit(0);
88
89         /* Show's over, let's continue */
90         lua_pushboolean(L, 1);
91         lua_pushnil(L);
92         return 2;
93 }
94
95 /* Syslog support */
96
97 char *facility_strings[] =      {       "auth",
98                                         "authpriv",
99                                         "cron",
100                                         "daemon",
101                                         "ftp",
102                                         "kern",
103                                         "local0",
104                                         "local1",
105                                         "local2",
106                                         "local3",
107                                         "local4",
108                                         "local5",
109                                         "local6",
110                                         "local7",
111                                         "lpr",
112                                         "mail",
113                                         "syslog",
114                                         "user",
115                                         "uucp",
116                                         NULL
117                                 };
118 int facility_constants[] =      {
119                                         LOG_AUTH,
120                                         LOG_AUTHPRIV,
121                                         LOG_CRON,
122                                         LOG_DAEMON,
123                                         LOG_FTP,
124                                         LOG_KERN,
125                                         LOG_LOCAL0,
126                                         LOG_LOCAL1,
127                                         LOG_LOCAL2,
128                                         LOG_LOCAL3,
129                                         LOG_LOCAL4,
130                                         LOG_LOCAL5,
131                                         LOG_LOCAL6,
132                                         LOG_LOCAL7,
133                                         LOG_LPR,
134                                         LOG_MAIL,
135                                         LOG_NEWS,
136                                         LOG_SYSLOG,
137                                         LOG_USER,
138                                         LOG_UUCP,
139                                         -1
140                                 };
141
142 /* "
143        The parameter ident in the call of openlog() is probably stored  as-is.
144        Thus,  if  the  string  it  points  to  is  changed, syslog() may start
145        prepending the changed string, and if the string it points to ceases to
146        exist,  the  results  are  undefined.  Most portable is to use a string
147        constant.
148    " -- syslog manpage
149 */ 
150 char* syslog_ident = NULL;
151
152 int lc_syslog_open(lua_State* L)
153 {
154         int facility = luaL_checkoption(L, 2, "daemon", &facility_strings);
155         facility = facility_constants[facility];
156
157         luaL_checkstring(L, 1);
158         
159         if(syslog_ident)
160                 free(syslog_ident);
161         
162         syslog_ident = strdup(lua_tostring(L, 1));
163         
164         openlog(syslog_ident, LOG_PID, facility);
165         return 0;
166 }
167
168 char *level_strings[] =         {
169                                 "debug",
170                                 "info",
171                                 "notice",
172                                 "warn",
173                                 "error",
174                                 NULL
175                         };
176 int level_constants[] =         {
177                                 LOG_DEBUG,
178                                 LOG_INFO,
179                                 LOG_NOTICE,
180                                 LOG_WARNING,
181                                 LOG_EMERG,
182                                 -1
183                         };
184 int lc_syslog_log(lua_State* L)
185 {
186         int level = luaL_checkoption(L, 1, "notice", &level_strings);
187         level = level_constants[level];
188
189         luaL_checkstring(L, 2);
190
191         syslog(level, "%s", lua_tostring(L, 2));
192         return 0;
193 }
194
195 int lc_syslog_close(lua_State* L)
196 {
197         closelog();
198         if(syslog_ident)
199         {
200                 free(syslog_ident);
201                 syslog_ident = NULL;
202         }
203         return 0;
204 }
205
206 int lc_syslog_setmask(lua_State* L)
207 {
208         int level_idx = luaL_checkoption(L, 1, "notice", &level_strings);
209         int mask = 0;
210         do
211         {
212                 mask |= LOG_MASK(level_constants[level_idx]);
213         } while (++level_idx<=4);
214
215         setlogmask(mask);
216         return 0;
217 }
218
219 /* getpid */
220
221 int lc_getpid(lua_State* L)
222 {
223         lua_pushinteger(L, getpid());
224         return 1;
225 }
226
227 /* Register functions */
228
229 int luaopen_util_pposix(lua_State *L)
230 {
231         lua_newtable(L);
232
233         lua_pushcfunction(L, lc_daemonize);
234         lua_setfield(L, -2, "daemonize");
235
236         lua_pushcfunction(L, lc_syslog_open);
237         lua_setfield(L, -2, "syslog_open");
238
239         lua_pushcfunction(L, lc_syslog_close);
240         lua_setfield(L, -2, "syslog_close");
241
242         lua_pushcfunction(L, lc_syslog_log);
243         lua_setfield(L, -2, "syslog_log");
244
245         lua_pushcfunction(L, lc_syslog_setmask);
246         lua_setfield(L, -2, "syslog_setminlevel");
247
248         lua_pushcfunction(L, lc_getpid);
249         lua_setfield(L, -2, "getpid");
250
251         lua_pushliteral(L, "pposix");
252         lua_setfield(L, -2, "_NAME");
253
254         lua_pushliteral(L, MODULE_VERSION);
255         lua_setfield(L, -2, "_VERSION");
256         
257         return 1;
258 };