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 : }
|