Branch data 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" // SEP
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 : 1 : 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 : 1 : PyObject *argv = PySys_GetObject("argv");
75 : :
76 [ - + ]: 1 : if (argv == NULL) {
77 : 0 : return(NULL);
78 : : }
79 : :
80 : 1 : argv_len = PyList_Size(argv);
81 [ - + ]: 1 : if (argv_len == -1) {
82 : 0 : PyErr_Clear();
83 : 0 : return(NULL);
84 : : }
85 [ - + ]: 1 : if (argv_len == 0) {
86 : 0 : return(NULL);
87 : : }
88 : :
89 : 1 : scriptobj = PyList_GetItem(argv, 0);
90 [ - + ]: 1 : if (!PyUnicode_Check(scriptobj)) {
91 : 0 : return(NULL);
92 : : }
93 : 1 : scriptlen = PyUnicode_GET_LENGTH(scriptobj);
94 [ - + ]: 1 : if (scriptlen == 0) {
95 : 0 : return(NULL);
96 : : }
97 : :
98 : 1 : slash = PyUnicode_FindChar(scriptobj, SEP, 0, scriptlen, -1);
99 [ - + ]: 1 : if (slash == -2)
100 : 0 : return NULL;
101 [ + - ]: 1 : if (slash != -1) {
102 : 1 : return PyUnicode_Substring(scriptobj, slash + 1, scriptlen);
103 : : } else {
104 : 0 : Py_INCREF(scriptobj);
105 : 0 : return(scriptobj);
106 : : }
107 : :
108 : : return(NULL);
109 : : }
110 : :
111 : :
112 : : static PyObject *
113 : 5 : syslog_openlog(PyObject * self, PyObject * args, PyObject *kwds)
114 : : {
115 : 5 : long logopt = 0;
116 : 5 : long facility = LOG_USER;
117 : 5 : PyObject *new_S_ident_o = NULL;
118 : : static char *keywords[] = {"ident", "logoption", "facility", 0};
119 : 5 : const char *ident = NULL;
120 : :
121 [ - + ]: 5 : if (!PyArg_ParseTupleAndKeywords(args, kwds,
122 : : "|Ull:openlog", keywords, &new_S_ident_o, &logopt, &facility))
123 : 0 : return NULL;
124 : :
125 [ + + ]: 5 : if (new_S_ident_o) {
126 : 4 : Py_INCREF(new_S_ident_o);
127 : : }
128 : :
129 : : /* get sys.argv[0] or NULL if we can't for some reason */
130 [ + + ]: 5 : if (!new_S_ident_o) {
131 : 1 : new_S_ident_o = syslog_get_argv();
132 : : }
133 : :
134 : 5 : Py_XDECREF(S_ident_o);
135 : 5 : 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 [ + - ]: 5 : if (S_ident_o) {
142 : 5 : ident = PyUnicode_AsUTF8(S_ident_o);
143 [ + + ]: 5 : if (ident == NULL)
144 : 1 : return NULL;
145 : : }
146 : :
147 [ - + ]: 4 : if (PySys_Audit("syslog.openlog", "sll", ident, logopt, facility) < 0) {
148 : 0 : return NULL;
149 : : }
150 : :
151 : 4 : openlog(ident, logopt, facility);
152 : 4 : S_log_open = 1;
153 : :
154 : 4 : Py_RETURN_NONE;
155 : : }
156 : :
157 : :
158 : : static PyObject *
159 : 3 : syslog_syslog(PyObject * self, PyObject * args)
160 : : {
161 : : PyObject *message_object;
162 : : const char *message;
163 : 3 : int priority = LOG_INFO;
164 : :
165 [ + + ]: 3 : if (!PyArg_ParseTuple(args, "iU;[priority,] message string",
166 : : &priority, &message_object)) {
167 : 2 : PyErr_Clear();
168 [ - + ]: 2 : if (!PyArg_ParseTuple(args, "U;[priority,] message string",
169 : : &message_object))
170 : 0 : return NULL;
171 : : }
172 : :
173 : 3 : message = PyUnicode_AsUTF8(message_object);
174 [ - + ]: 3 : if (message == NULL)
175 : 0 : return NULL;
176 : :
177 [ - + ]: 3 : if (PySys_Audit("syslog.syslog", "is", priority, message) < 0) {
178 : 0 : return NULL;
179 : : }
180 : :
181 : : /* if log is not opened, open it now */
182 [ - + ]: 3 : if (!S_log_open) {
183 : : PyObject *openargs;
184 : :
185 : : /* Continue even if PyTuple_New fails, because openlog(3) is optional.
186 : : * So, we can still do logging in the unlikely event things are so hosed
187 : : * that we can't do this tuple.
188 : : */
189 [ # # ]: 0 : if ((openargs = PyTuple_New(0))) {
190 : 0 : PyObject *openlog_ret = syslog_openlog(self, openargs, NULL);
191 : 0 : Py_XDECREF(openlog_ret);
192 : 0 : Py_DECREF(openargs);
193 : : }
194 : : }
195 : :
196 : 3 : Py_BEGIN_ALLOW_THREADS;
197 : 3 : syslog(priority, "%s", message);
198 : 3 : Py_END_ALLOW_THREADS;
199 : 3 : Py_RETURN_NONE;
200 : : }
201 : :
202 : : static PyObject *
203 : 1 : syslog_closelog(PyObject *self, PyObject *unused)
204 : : {
205 [ - + ]: 1 : if (PySys_Audit("syslog.closelog", NULL) < 0) {
206 : 0 : return NULL;
207 : : }
208 [ + - ]: 1 : if (S_log_open) {
209 : 1 : closelog();
210 [ + - ]: 1 : Py_CLEAR(S_ident_o);
211 : 1 : S_log_open = 0;
212 : : }
213 : 1 : Py_RETURN_NONE;
214 : : }
215 : :
216 : : static PyObject *
217 : 1 : syslog_setlogmask(PyObject *self, PyObject *args)
218 : : {
219 : : long maskpri, omaskpri;
220 : :
221 [ - + ]: 1 : if (!PyArg_ParseTuple(args, "l;mask for priority", &maskpri))
222 : 0 : return NULL;
223 [ + - - + ]: 1 : if (PySys_Audit("syslog.setlogmask", "(O)", args ? args : Py_None) < 0) {
224 : 0 : return NULL;
225 : : }
226 : 1 : omaskpri = setlogmask(maskpri);
227 : 1 : return PyLong_FromLong(omaskpri);
228 : : }
229 : :
230 : : static PyObject *
231 : 1 : syslog_log_mask(PyObject *self, PyObject *args)
232 : : {
233 : : long mask;
234 : : long pri;
235 [ - + ]: 1 : if (!PyArg_ParseTuple(args, "l:LOG_MASK", &pri))
236 : 0 : return NULL;
237 : 1 : mask = LOG_MASK(pri);
238 : 1 : return PyLong_FromLong(mask);
239 : : }
240 : :
241 : : static PyObject *
242 : 1 : syslog_log_upto(PyObject *self, PyObject *args)
243 : : {
244 : : long mask;
245 : : long pri;
246 [ - + ]: 1 : if (!PyArg_ParseTuple(args, "l:LOG_UPTO", &pri))
247 : 0 : return NULL;
248 : 1 : mask = LOG_UPTO(pri);
249 : 1 : return PyLong_FromLong(mask);
250 : : }
251 : :
252 : : /* List of functions defined in the module */
253 : :
254 : : static PyMethodDef syslog_methods[] = {
255 : : {"openlog", _PyCFunction_CAST(syslog_openlog), METH_VARARGS | METH_KEYWORDS},
256 : : {"closelog", syslog_closelog, METH_NOARGS},
257 : : {"syslog", syslog_syslog, METH_VARARGS},
258 : : {"setlogmask", syslog_setlogmask, METH_VARARGS},
259 : : {"LOG_MASK", syslog_log_mask, METH_VARARGS},
260 : : {"LOG_UPTO", syslog_log_upto, METH_VARARGS},
261 : : {NULL, NULL, 0}
262 : : };
263 : :
264 : :
265 : : static int
266 : 2 : syslog_exec(PyObject *module)
267 : : {
268 : : #define ADD_INT_MACRO(module, macro) \
269 : : do { \
270 : : if (PyModule_AddIntConstant(module, #macro, macro) < 0) { \
271 : : return -1; \
272 : : } \
273 : : } while (0)
274 : : /* Priorities */
275 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_EMERG);
276 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_ALERT);
277 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_CRIT);
278 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_ERR);
279 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_WARNING);
280 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_NOTICE);
281 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_INFO);
282 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_DEBUG);
283 : :
284 : : /* openlog() option flags */
285 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_PID);
286 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_CONS);
287 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_NDELAY);
288 : : #ifdef LOG_ODELAY
289 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_ODELAY);
290 : : #endif
291 : : #ifdef LOG_NOWAIT
292 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_NOWAIT);
293 : : #endif
294 : : #ifdef LOG_PERROR
295 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_PERROR);
296 : : #endif
297 : :
298 : : /* Facilities */
299 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_KERN);
300 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_USER);
301 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_MAIL);
302 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_DAEMON);
303 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_AUTH);
304 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LPR);
305 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LOCAL0);
306 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LOCAL1);
307 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LOCAL2);
308 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LOCAL3);
309 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LOCAL4);
310 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LOCAL5);
311 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LOCAL6);
312 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_LOCAL7);
313 : :
314 : : #ifndef LOG_SYSLOG
315 : : #define LOG_SYSLOG LOG_DAEMON
316 : : #endif
317 : : #ifndef LOG_NEWS
318 : : #define LOG_NEWS LOG_MAIL
319 : : #endif
320 : : #ifndef LOG_UUCP
321 : : #define LOG_UUCP LOG_MAIL
322 : : #endif
323 : : #ifndef LOG_CRON
324 : : #define LOG_CRON LOG_DAEMON
325 : : #endif
326 : :
327 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_SYSLOG);
328 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_CRON);
329 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_UUCP);
330 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_NEWS);
331 : :
332 : : #ifdef LOG_AUTHPRIV
333 [ - + ]: 2 : ADD_INT_MACRO(module, LOG_AUTHPRIV);
334 : : #endif
335 : :
336 : 2 : return 0;
337 : : }
338 : :
339 : : static PyModuleDef_Slot syslog_slots[] = {
340 : : {Py_mod_exec, syslog_exec},
341 : : {0, NULL}
342 : : };
343 : :
344 : : /* Initialization function for the module */
345 : :
346 : : static struct PyModuleDef syslogmodule = {
347 : : PyModuleDef_HEAD_INIT,
348 : : .m_name = "syslog",
349 : : .m_size = 0,
350 : : .m_methods = syslog_methods,
351 : : .m_slots = syslog_slots,
352 : : };
353 : :
354 : : PyMODINIT_FUNC
355 : 2 : PyInit_syslog(void)
356 : : {
357 : 2 : return PyModuleDef_Init(&syslogmodule);
358 : : }
|