Line data Source code
1 : /***********************************************************
2 : Copyright 1994 by Lance Ellinghouse,
3 : Cathedral City, California Republic, United States of America.
4 :
5 : All Rights Reserved
6 :
7 : Permission to use, copy, modify, and distribute this software and its
8 : documentation for any purpose and without fee is hereby granted,
9 : provided that the above copyright notice appear in all copies and that
10 : both that copyright notice and this permission notice appear in
11 : supporting documentation, and that the name of Lance Ellinghouse
12 : not be used in advertising or publicity pertaining to distribution
13 : of the software without specific, written prior permission.
14 :
15 : LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 : THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 : FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE BE LIABLE FOR ANY SPECIAL,
18 : INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
19 : FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 : NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 : WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 :
23 : ******************************************************************/
24 :
25 : /******************************************************************
26 :
27 : Revision history:
28 :
29 : 2010/04/20 (Sean Reifschneider)
30 : - Use basename(sys.argv[0]) for the default "ident".
31 : - Arguments to openlog() are now keyword args and are all optional.
32 : - syslog() calls openlog() if it hasn't already been called.
33 :
34 : 1998/04/28 (Sean Reifschneider)
35 : - When facility not specified to syslog() method, use default from openlog()
36 : (This is how it was claimed to work in the documentation)
37 : - Potential resource leak of o_ident, now cleaned up in closelog()
38 : - Minor comment accuracy fix.
39 :
40 : 95/06/29 (Steve Clift)
41 : - Changed arg parsing to use PyArg_ParseTuple.
42 : - Added PyErr_Clear() call(s) where needed.
43 : - Fix core dumps if user message contains format specifiers.
44 : - Change openlog arg defaults to match normal syslog behavior.
45 : - Plug memory leak in openlog().
46 : - Fix setlogmask() to return previous mask value.
47 :
48 : ******************************************************************/
49 :
50 : /* syslog module */
51 :
52 : #include "Python.h"
53 : #include "osdefs.h"
54 :
55 : #include <syslog.h>
56 :
57 : /* only one instance, only one syslog, so globals should be ok */
58 : static PyObject *S_ident_o = NULL; /* identifier, held by openlog() */
59 : static char S_log_open = 0;
60 :
61 :
62 : static PyObject *
63 0 : syslog_get_argv(void)
64 : {
65 : /* Figure out what to use for as the program "ident" for openlog().
66 : * This swallows exceptions and continues rather than failing out,
67 : * because the syslog module can still be used because openlog(3)
68 : * is optional.
69 : */
70 :
71 : Py_ssize_t argv_len, scriptlen;
72 : PyObject *scriptobj;
73 : Py_ssize_t slash;
74 0 : PyObject *argv = PySys_GetObject("argv");
75 :
76 0 : if (argv == NULL) {
77 0 : return(NULL);
78 : }
79 :
80 0 : argv_len = PyList_Size(argv);
81 0 : if (argv_len == -1) {
82 0 : PyErr_Clear();
83 0 : return(NULL);
84 : }
85 0 : if (argv_len == 0) {
86 0 : return(NULL);
87 : }
88 :
89 0 : scriptobj = PyList_GetItem(argv, 0);
90 0 : if (!PyUnicode_Check(scriptobj)) {
91 0 : return(NULL);
92 : }
93 0 : scriptlen = PyUnicode_GET_LENGTH(scriptobj);
94 0 : if (scriptlen == 0) {
95 0 : return(NULL);
96 : }
97 :
98 0 : slash = PyUnicode_FindChar(scriptobj, SEP, 0, scriptlen, -1);
99 0 : if (slash == -2)
100 0 : return NULL;
101 0 : if (slash != -1) {
102 0 : return PyUnicode_Substring(scriptobj, slash, scriptlen);
103 : } else {
104 0 : Py_INCREF(scriptobj);
105 0 : return(scriptobj);
106 : }
107 :
108 : return(NULL);
109 : }
110 :
111 :
112 : static PyObject *
113 0 : syslog_openlog(PyObject * self, PyObject * args, PyObject *kwds)
114 : {
115 0 : long logopt = 0;
116 0 : long facility = LOG_USER;
117 0 : PyObject *new_S_ident_o = NULL;
118 : static char *keywords[] = {"ident", "logoption", "facility", 0};
119 0 : char *ident = NULL;
120 :
121 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds,
122 : "|Ull:openlog", keywords, &new_S_ident_o, &logopt, &facility))
123 0 : return NULL;
124 :
125 0 : if (new_S_ident_o) {
126 0 : Py_INCREF(new_S_ident_o);
127 : }
128 :
129 : /* get sys.argv[0] or NULL if we can't for some reason */
130 0 : if (!new_S_ident_o) {
131 0 : new_S_ident_o = syslog_get_argv();
132 : }
133 :
134 0 : Py_XDECREF(S_ident_o);
135 0 : S_ident_o = new_S_ident_o;
136 :
137 : /* At this point, S_ident_o should be INCREF()ed. openlog(3) does not
138 : * make a copy, and syslog(3) later uses it. We can't garbagecollect it
139 : * If NULL, just let openlog figure it out (probably using C argv[0]).
140 : */
141 0 : if (S_ident_o) {
142 0 : ident = _PyUnicode_AsString(S_ident_o);
143 0 : if (ident == NULL)
144 0 : return NULL;
145 : }
146 :
147 0 : openlog(ident, logopt, facility);
148 0 : S_log_open = 1;
149 :
150 0 : Py_INCREF(Py_None);
151 0 : return Py_None;
152 : }
153 :
154 :
155 : static PyObject *
156 0 : syslog_syslog(PyObject * self, PyObject * args)
157 : {
158 : PyObject *message_object;
159 : const char *message;
160 0 : int priority = LOG_INFO;
161 :
162 0 : if (!PyArg_ParseTuple(args, "iU;[priority,] message string",
163 : &priority, &message_object)) {
164 0 : PyErr_Clear();
165 0 : if (!PyArg_ParseTuple(args, "U;[priority,] message string",
166 : &message_object))
167 0 : return NULL;
168 : }
169 :
170 0 : message = _PyUnicode_AsString(message_object);
171 0 : if (message == NULL)
172 0 : return NULL;
173 :
174 : /* if log is not opened, open it now */
175 0 : if (!S_log_open) {
176 : PyObject *openargs;
177 :
178 : /* Continue even if PyTuple_New fails, because openlog(3) is optional.
179 : * So, we can still do loggin in the unlikely event things are so hosed
180 : * that we can't do this tuple.
181 : */
182 0 : if ((openargs = PyTuple_New(0))) {
183 0 : PyObject *openlog_ret = syslog_openlog(self, openargs, NULL);
184 0 : Py_XDECREF(openlog_ret);
185 0 : Py_DECREF(openargs);
186 : }
187 : }
188 :
189 0 : Py_BEGIN_ALLOW_THREADS;
190 0 : syslog(priority, "%s", message);
191 0 : Py_END_ALLOW_THREADS;
192 0 : Py_RETURN_NONE;
193 : }
194 :
195 : static PyObject *
196 0 : syslog_closelog(PyObject *self, PyObject *unused)
197 : {
198 0 : if (S_log_open) {
199 0 : closelog();
200 0 : Py_XDECREF(S_ident_o);
201 0 : S_ident_o = NULL;
202 0 : S_log_open = 0;
203 : }
204 0 : Py_INCREF(Py_None);
205 0 : return Py_None;
206 : }
207 :
208 : static PyObject *
209 0 : syslog_setlogmask(PyObject *self, PyObject *args)
210 : {
211 : long maskpri, omaskpri;
212 :
213 0 : if (!PyArg_ParseTuple(args, "l;mask for priority", &maskpri))
214 0 : return NULL;
215 0 : omaskpri = setlogmask(maskpri);
216 0 : return PyLong_FromLong(omaskpri);
217 : }
218 :
219 : static PyObject *
220 0 : syslog_log_mask(PyObject *self, PyObject *args)
221 : {
222 : long mask;
223 : long pri;
224 0 : if (!PyArg_ParseTuple(args, "l:LOG_MASK", &pri))
225 0 : return NULL;
226 0 : mask = LOG_MASK(pri);
227 0 : return PyLong_FromLong(mask);
228 : }
229 :
230 : static PyObject *
231 0 : syslog_log_upto(PyObject *self, PyObject *args)
232 : {
233 : long mask;
234 : long pri;
235 0 : if (!PyArg_ParseTuple(args, "l:LOG_UPTO", &pri))
236 0 : return NULL;
237 0 : mask = LOG_UPTO(pri);
238 0 : return PyLong_FromLong(mask);
239 : }
240 :
241 : /* List of functions defined in the module */
242 :
243 : static PyMethodDef syslog_methods[] = {
244 : {"openlog", (PyCFunction) syslog_openlog, METH_VARARGS | METH_KEYWORDS},
245 : {"closelog", syslog_closelog, METH_NOARGS},
246 : {"syslog", syslog_syslog, METH_VARARGS},
247 : {"setlogmask", syslog_setlogmask, METH_VARARGS},
248 : {"LOG_MASK", syslog_log_mask, METH_VARARGS},
249 : {"LOG_UPTO", syslog_log_upto, METH_VARARGS},
250 : {NULL, NULL, 0}
251 : };
252 :
253 : /* Initialization function for the module */
254 :
255 :
256 : static struct PyModuleDef syslogmodule = {
257 : PyModuleDef_HEAD_INIT,
258 : "syslog",
259 : NULL,
260 : -1,
261 : syslog_methods,
262 : NULL,
263 : NULL,
264 : NULL,
265 : NULL
266 : };
267 :
268 : PyMODINIT_FUNC
269 0 : PyInit_syslog(void)
270 : {
271 : PyObject *m;
272 :
273 : /* Create the module and add the functions */
274 0 : m = PyModule_Create(&syslogmodule);
275 0 : if (m == NULL)
276 0 : return NULL;
277 :
278 : /* Add some symbolic constants to the module */
279 :
280 : /* Priorities */
281 0 : PyModule_AddIntConstant(m, "LOG_EMERG", LOG_EMERG);
282 0 : PyModule_AddIntConstant(m, "LOG_ALERT", LOG_ALERT);
283 0 : PyModule_AddIntConstant(m, "LOG_CRIT", LOG_CRIT);
284 0 : PyModule_AddIntConstant(m, "LOG_ERR", LOG_ERR);
285 0 : PyModule_AddIntConstant(m, "LOG_WARNING", LOG_WARNING);
286 0 : PyModule_AddIntConstant(m, "LOG_NOTICE", LOG_NOTICE);
287 0 : PyModule_AddIntConstant(m, "LOG_INFO", LOG_INFO);
288 0 : PyModule_AddIntConstant(m, "LOG_DEBUG", LOG_DEBUG);
289 :
290 : /* openlog() option flags */
291 0 : PyModule_AddIntConstant(m, "LOG_PID", LOG_PID);
292 0 : PyModule_AddIntConstant(m, "LOG_CONS", LOG_CONS);
293 0 : PyModule_AddIntConstant(m, "LOG_NDELAY", LOG_NDELAY);
294 : #ifdef LOG_ODELAY
295 0 : PyModule_AddIntConstant(m, "LOG_ODELAY", LOG_ODELAY);
296 : #endif
297 : #ifdef LOG_NOWAIT
298 0 : PyModule_AddIntConstant(m, "LOG_NOWAIT", LOG_NOWAIT);
299 : #endif
300 : #ifdef LOG_PERROR
301 0 : PyModule_AddIntConstant(m, "LOG_PERROR", LOG_PERROR);
302 : #endif
303 :
304 : /* Facilities */
305 0 : PyModule_AddIntConstant(m, "LOG_KERN", LOG_KERN);
306 0 : PyModule_AddIntConstant(m, "LOG_USER", LOG_USER);
307 0 : PyModule_AddIntConstant(m, "LOG_MAIL", LOG_MAIL);
308 0 : PyModule_AddIntConstant(m, "LOG_DAEMON", LOG_DAEMON);
309 0 : PyModule_AddIntConstant(m, "LOG_AUTH", LOG_AUTH);
310 0 : PyModule_AddIntConstant(m, "LOG_LPR", LOG_LPR);
311 0 : PyModule_AddIntConstant(m, "LOG_LOCAL0", LOG_LOCAL0);
312 0 : PyModule_AddIntConstant(m, "LOG_LOCAL1", LOG_LOCAL1);
313 0 : PyModule_AddIntConstant(m, "LOG_LOCAL2", LOG_LOCAL2);
314 0 : PyModule_AddIntConstant(m, "LOG_LOCAL3", LOG_LOCAL3);
315 0 : PyModule_AddIntConstant(m, "LOG_LOCAL4", LOG_LOCAL4);
316 0 : PyModule_AddIntConstant(m, "LOG_LOCAL5", LOG_LOCAL5);
317 0 : PyModule_AddIntConstant(m, "LOG_LOCAL6", LOG_LOCAL6);
318 0 : PyModule_AddIntConstant(m, "LOG_LOCAL7", LOG_LOCAL7);
319 :
320 : #ifndef LOG_SYSLOG
321 : #define LOG_SYSLOG LOG_DAEMON
322 : #endif
323 : #ifndef LOG_NEWS
324 : #define LOG_NEWS LOG_MAIL
325 : #endif
326 : #ifndef LOG_UUCP
327 : #define LOG_UUCP LOG_MAIL
328 : #endif
329 : #ifndef LOG_CRON
330 : #define LOG_CRON LOG_DAEMON
331 : #endif
332 :
333 0 : PyModule_AddIntConstant(m, "LOG_SYSLOG", LOG_SYSLOG);
334 0 : PyModule_AddIntConstant(m, "LOG_CRON", LOG_CRON);
335 0 : PyModule_AddIntConstant(m, "LOG_UUCP", LOG_UUCP);
336 0 : PyModule_AddIntConstant(m, "LOG_NEWS", LOG_NEWS);
337 :
338 : #ifdef LOG_AUTHPRIV
339 0 : PyModule_AddIntConstant(m, "LOG_AUTHPRIV", LOG_AUTHPRIV);
340 : #endif
341 :
342 0 : return m;
343 : }
|