mod_posix: Support for logging to syslog (log = 'syslog' in config)
[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 #include <stdlib.h>
25 #include <unistd.h>
26 #include <libgen.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30
31 #include <syslog.h>
32
33 #include <string.h>
34
35 #include "lua.h"
36 #include "lauxlib.h"
37
38 /* Daemonization support */
39
40 static int daemonize(lua_State *L)
41 {
42
43         pid_t pid;
44         
45         if ( getppid() == 1 )
46         {
47                 lua_pushboolean(L, 0);
48                 lua_pushstring(L, "already-daemonized");
49                 return 2;
50         }
51         
52         /* Attempt initial fork */
53         if((pid = fork()) < 0)
54         {
55                 /* Forking failed */
56                 lua_pushboolean(L, 0);
57                 lua_pushstring(L, "fork-failed");
58                 return 2;
59         }
60         else if(pid != 0)
61         {
62                 /* We are the parent process */
63                 lua_pushboolean(L, 1);
64                 lua_pushnumber(L, pid);
65                 return 2;
66         }
67         
68         /* and we are the child process */
69         if(setsid() == -1)
70         {
71                 /* We failed to become session leader */
72                 /* (we probably already were) */
73                 lua_pushboolean(L, 0);
74                 lua_pushstring(L, "setsid-failed");
75                 return 2;
76         }
77
78         /* Close stdin, stdout, stderr */
79 /*      close(0);
80         close(1);
81         close(2);
82 */
83         /* Final fork, use it wisely */
84         if(fork())
85                 exit(0);
86
87         /* Show's over, let's continue */
88         lua_pushboolean(L, 1);
89         lua_pushnil(L);
90         return 2;
91 }
92
93 /* Syslog support */
94
95 char *facility_strings[] =      {       "auth",
96                                         "authpriv",
97                                         "cron",
98                                         "daemon",
99                                         "ftp",
100                                         "kern",
101                                         "local0",
102                                         "local1",
103                                         "local2",
104                                         "local3",
105                                         "local4",
106                                         "local5",
107                                         "local6",
108                                         "local7",
109                                         "lpr",
110                                         "mail",
111                                         "syslog",
112                                         "user",
113                                         "uucp",
114                                         NULL
115                                 };
116 int facility_constants[] =      {
117                                         LOG_AUTH,
118                                         LOG_AUTHPRIV,
119                                         LOG_CRON,
120                                         LOG_DAEMON,
121                                         LOG_FTP,
122                                         LOG_KERN,
123                                         LOG_LOCAL0,
124                                         LOG_LOCAL1,
125                                         LOG_LOCAL2,
126                                         LOG_LOCAL3,
127                                         LOG_LOCAL4,
128                                         LOG_LOCAL5,
129                                         LOG_LOCAL6,
130                                         LOG_LOCAL7,
131                                         LOG_LPR,
132                                         LOG_MAIL,
133                                         LOG_NEWS,
134                                         LOG_SYSLOG,
135                                         LOG_USER,
136                                         LOG_UUCP,
137                                         -1
138                                 };
139
140 /* "
141        The parameter ident in the call of openlog() is probably stored  as-is.
142        Thus,  if  the  string  it  points  to  is  changed, syslog() may start
143        prepending the changed string, and if the string it points to ceases to
144        exist,  the  results  are  undefined.  Most portable is to use a string
145        constant.
146    " -- syslog manpage
147 */ 
148 char* syslog_ident = NULL;
149
150 int syslog_open(lua_State* L)
151 {
152         int facility = luaL_checkoption(L, 2, "daemon", &facility_strings);
153         facility = facility_constants[facility];
154
155         luaL_checkstring(L, 1);
156         
157         if(syslog_ident)
158                 free(syslog_ident);
159         
160         syslog_ident = strdup(lua_tostring(L, 1));
161         
162         openlog(syslog_ident, LOG_PID, facility);
163         return 0;
164 }
165
166 char *level_strings[] =         {
167                                 "debug",
168                                 "info",
169                                 "notice",
170                                 "warn",
171                                 "error",
172                                 NULL
173                         };
174 int level_constants[] =         {
175                                 LOG_DEBUG,
176                                 LOG_INFO,
177                                 LOG_NOTICE,
178                                 LOG_WARNING,
179                                 LOG_EMERG,
180                                 -1
181                         };
182 int syslog_log(lua_State* L)
183 {
184         int level = luaL_checkoption(L, 1, "notice", &level_strings);
185         level = level_constants[level];
186
187         luaL_checkstring(L, 2);
188
189         syslog(level, "%s", lua_tostring(L, 2));
190         return 0;
191 }
192
193 int syslog_close(lua_State* L)
194 {
195         closelog();
196         if(syslog_ident)
197         {
198                 free(syslog_ident);
199                 syslog_ident = NULL;
200         }
201         return 0;
202 }
203
204 int luaopen_util_pposix(lua_State *L)
205 {
206         lua_newtable(L);
207
208         lua_pushcfunction(L, daemonize);
209         lua_setfield(L, -2, "daemonize");
210
211         lua_pushcfunction(L, syslog_open);
212         lua_setfield(L, -2, "syslog_open");
213
214         lua_pushcfunction(L, syslog_close);
215         lua_setfield(L, -2, "syslog_close");
216
217         lua_pushcfunction(L, syslog_log);
218         lua_setfield(L, -2, "syslog_log");
219
220         return 1;
221 };