From 13daf12b47f628a77dbd174a43dc72ed32f00b5b Mon Sep 17 00:00:00 2001 From: Sean Reifscheider Date: Fri, 23 Apr 2010 09:29:52 +0000 Subject: Port of issue8451 to python3: Syslog use sys.argv[0] for ident. --- Doc/library/syslog.rst | 85 +++++++++++++++++++++++++++++---------- Misc/NEWS | 4 ++ Modules/syslogmodule.c | 105 ++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 159 insertions(+), 35 deletions(-) diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst index 89dd38f..c25ed41 100644 --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -10,42 +10,66 @@ This module provides an interface to the Unix ``syslog`` library routines. Refer to the Unix manual pages for a detailed description of the ``syslog`` facility. +This module wraps the system ``syslog`` module. A pure Python +library that can speak to a syslog server is available in +the :mod:`logging.handlers` module as :class:`SysLogHandler`. + The module defines the following functions: .. function:: syslog([priority,] message) - Send the string *message* to the system logger. A trailing newline is added if - necessary. Each message is tagged with a priority composed of a *facility* and - a *level*. The optional *priority* argument, which defaults to - :const:`LOG_INFO`, determines the message priority. If the facility is not - encoded in *priority* using logical-or (``LOG_INFO | LOG_USER``), the value - given in the :func:`openlog` call is used. + Send the string *message* to the system logger. A trailing newline is + added if necessary. Each message is tagged with a priority composed + of a *facility* and a *level*. The optional *priority* argument, which + defaults to :const:`LOG_INFO`, determines the message priority. If the + facility is not encoded in *priority* using logical-or (``LOG_INFO | + LOG_USER``), the value given in the :func:`openlog` call is used. + + If :func:`openlog` has not been called prior to the call to + :func:'syslog', ``openlog()`` will be called with no arguments. + +.. function:: openlog([ident[, logopt[, facility]]]) -.. function:: openlog(ident[, logopt[, facility]]) + Logging options of subsequent :func:`syslog` calls can be set by + calling :func:`openlog`. :func:`syslog` will call :func:`openlog` + with no arguments if the log is not currently open. - Logging options other than the defaults can be set by explicitly opening the log - file with :func:`openlog` prior to calling :func:`syslog`. The defaults are - (usually) *ident* = ``'syslog'``, *logopt* = ``0``, *facility* = - :const:`LOG_USER`. The *ident* argument is a string which is prepended to every - message. The optional *logopt* argument is a bit field - see below for possible - values to combine. The optional *facility* argument sets the default facility - for messages which do not have a facility explicitly encoded. + The optional *ident* keyword argument is a string which is prepended + to every message, and defaults to ''sys.argv[0]'' with leading + path components stripped. The optional *logopt* keyword argument + (default=0) is a bit field - see below for possible values to combine. + The optional *facility* keyword argument (default=:const:`LOG_USER`) + sets the default facility for messages which do not have a facility + explicitly encoded. + + .. versionchanged::3.2 + In previous versions, keyword arguments were not allowed, and *ident* + was required. The default for *ident* was dependent on the system + libraries, and often was ''python'' instead of the name of the + python program file. .. function:: closelog() - Close the log file. + Reset the syslog module values and call the system library + ''closelog()''. + + This causes the module to behave as it does when initially imported. + For example, :func:'openlog' will be called on the first :func:'syslog' + call (if :func:'openlog' hasn't already been called), and *ident* + and other :func:'openlog' parameters are reset to defaults. .. function:: setlogmask(maskpri) - Set the priority mask to *maskpri* and return the previous mask value. Calls to - :func:`syslog` with a priority level not set in *maskpri* are ignored. The - default is to log all priorities. The function ``LOG_MASK(pri)`` calculates the - mask for the individual priority *pri*. The function ``LOG_UPTO(pri)`` - calculates the mask for all priorities up to and including *pri*. + Set the priority mask to *maskpri* and return the previous mask value. + Calls to :func:`syslog` with a priority level not set in *maskpri* + are ignored. The default is to log all priorities. The function + ``LOG_MASK(pri)`` calculates the mask for the individual priority + *pri*. The function ``LOG_UPTO(pri)`` calculates the mask for all + priorities up to and including *pri*. The module defines the following constants: @@ -63,3 +87,24 @@ Log options: :const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, :const:`LOG_NOWAIT` and :const:`LOG_PERROR` if defined in ````. + +Examples +-------- + +Simple example +~~~~~~~~~~~~~~ + +A simple set of examples:: + + import syslog + + syslog.syslog('Processing started') + if error: + syslog.syslog(syslog.LOG_ERR, 'Processing started') + +An example of setting some log options, these would include the process ID +in logged messages, and write the messages to the destination facility +used for mail logging:: + + syslog.openlog(logopt=syslog.LOG_PID, facility=syslog.LOG_MAIL) + syslog.syslog('E-mail processing initiated...') diff --git a/Misc/NEWS b/Misc/NEWS index c65f8ab..d227973 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -329,6 +329,10 @@ C-API Library ------- +- Issue #8451: Syslog module now uses basename(sys.argv[0]) instead of + the string "python" as the *ident*. openlog() arguments are all optional + and keywords. + - Issue #8108: Fix the unwrap() method of SSL objects when the socket has a non-infinite timeout. Also make that method friendlier with applications wanting to continue using the socket in clear-text mode, by disabling diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c index c6a3b36..2281c1d 100644 --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -26,6 +26,11 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Revision history: +2010/04/20 (Sean Reifschneider) + - Use basename(sys.argv[0]) for the default "ident". + - Arguments to openlog() are now keyword args and are all optional. + - syslog() calls openlog() if it hasn't already been called. + 1998/04/28 (Sean Reifschneider) - When facility not specified to syslog() method, use default from openlog() (This is how it was claimed to work in the documentation) @@ -45,6 +50,7 @@ Revision history: /* syslog module */ #include "Python.h" +#include "osdefs.h" #include @@ -52,30 +58,83 @@ Revision history: static PyObject *S_ident_o = NULL; /* identifier, held by openlog() */ +static PyObject * +syslog_get_argv(void) +{ + /* Figure out what to use for as the program "ident" for openlog(). + * This swallows exceptions and continues rather than failing out, + * because the syslog module can still be used because openlog(3) + * is optional. + */ + + Py_ssize_t argv_len; + PyObject *scriptobj; + char *atslash; + PyObject *argv = PySys_GetObject("argv"); + + if (argv == NULL) { + return(NULL); + } + + argv_len = PyList_Size(argv); + if (argv_len == -1) { + PyErr_Clear(); + return(NULL); + } + if (argv_len == 0) { + return(NULL); + } + + scriptobj = PyList_GetItem(argv, 0); + if (!PyUnicode_Check(scriptobj)) { + return(NULL); + } + if (PyUnicode_GET_SIZE(scriptobj) == 0) { + return(NULL); + } + + atslash = strrchr(_PyUnicode_AsString(scriptobj), SEP); + if (atslash) { + return(PyUnicode_FromString(atslash + 1)); + } else { + Py_INCREF(scriptobj); + return(scriptobj); + } + + return(NULL); +} + + static PyObject * -syslog_openlog(PyObject * self, PyObject * args) +syslog_openlog(PyObject * self, PyObject * args, PyObject *kwds) { long logopt = 0; long facility = LOG_USER; - PyObject *new_S_ident_o; - const char *ident; + PyObject *new_S_ident_o = NULL; + static char *keywords[] = {"ident", "logoption", "facility", 0}; - if (!PyArg_ParseTuple(args, - "U|ll;ident string [, logoption [, facility]]", - &new_S_ident_o, &logopt, &facility)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "|Ull:openlog", keywords, &new_S_ident_o, &logopt, &facility)) return NULL; - /* This is needed because openlog() does NOT make a copy - * and syslog() later uses it.. cannot trash it. - */ + if (new_S_ident_o) { + Py_INCREF(new_S_ident_o); + } + + /* get sys.argv[0] or NULL if we can't for some reason */ + if (!new_S_ident_o) { + new_S_ident_o = syslog_get_argv(); + } + Py_XDECREF(S_ident_o); S_ident_o = new_S_ident_o; - Py_INCREF(S_ident_o); - ident = _PyUnicode_AsString(S_ident_o); - if (ident == NULL) - return NULL; - openlog(ident, logopt, facility); + /* At this point, S_ident_o should be INCREF()ed. openlog(3) does not + * make a copy, and syslog(3) later uses it. We can't garbagecollect it + * If NULL, just let openlog figure it out (probably using C argv[0]). + */ + + openlog(S_ident_o ? _PyUnicode_AsString(S_ident_o) : NULL, logopt, facility); Py_INCREF(Py_None); return Py_None; @@ -100,6 +159,22 @@ syslog_syslog(PyObject * self, PyObject * args) message = _PyUnicode_AsString(message_object); if (message == NULL) return NULL; + + /* call openlog if no current identifier */ + if (!S_ident_o) { + PyObject *openargs; + + /* Continue even if PyTuple_New fails, because openlog(3) is optional. + * So, we can still do loggin in the unlikely event things are so hosed + * that we can't do this tuple. + */ + if ((openargs = PyTuple_New(0))) { + PyObject *openlog_ret = syslog_openlog(self, openargs, NULL); + Py_XDECREF(openlog_ret); + Py_DECREF(openargs); + } + } + Py_BEGIN_ALLOW_THREADS; syslog(priority, "%s", message); Py_END_ALLOW_THREADS; @@ -152,7 +227,7 @@ syslog_log_upto(PyObject *self, PyObject *args) /* List of functions defined in the module */ static PyMethodDef syslog_methods[] = { - {"openlog", syslog_openlog, METH_VARARGS}, + {"openlog", (PyCFunction) syslog_openlog, METH_VARARGS | METH_KEYWORDS}, {"closelog", syslog_closelog, METH_NOARGS}, {"syslog", syslog_syslog, METH_VARARGS}, {"setlogmask", syslog_setlogmask, METH_VARARGS}, -- cgit v0.12