Port of issue8451 to python3: Syslog use sys.argv[0] for ident.

This commit is contained in:
Sean Reifscheider 2010-04-23 09:29:52 +00:00
parent 2c4f98b3c5
commit 13daf12b47
3 changed files with 159 additions and 35 deletions

View File

@ -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`` Refer to the Unix manual pages for a detailed description of the ``syslog``
facility. 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: The module defines the following functions:
.. function:: syslog([priority,] message) .. function:: syslog([priority,] message)
Send the string *message* to the system logger. A trailing newline is added if Send the string *message* to the system logger. A trailing newline is
necessary. Each message is tagged with a priority composed of a *facility* and added if necessary. Each message is tagged with a priority composed
a *level*. The optional *priority* argument, which defaults to of a *facility* and a *level*. The optional *priority* argument, which
:const:`LOG_INFO`, determines the message priority. If the facility is not defaults to :const:`LOG_INFO`, determines the message priority. If the
encoded in *priority* using logical-or (``LOG_INFO | LOG_USER``), the value facility is not encoded in *priority* using logical-or (``LOG_INFO |
given in the :func:`openlog` call is used. 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 other than the defaults can be set by explicitly opening the log Logging options of subsequent :func:`syslog` calls can be set by
file with :func:`openlog` prior to calling :func:`syslog`. The defaults are calling :func:`openlog`. :func:`syslog` will call :func:`openlog`
(usually) *ident* = ``'syslog'``, *logopt* = ``0``, *facility* = with no arguments if the log is not currently open.
: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 The optional *ident* keyword argument is a string which is prepended
values to combine. The optional *facility* argument sets the default facility to every message, and defaults to ''sys.argv[0]'' with leading
for messages which do not have a facility explicitly encoded. 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() .. 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) .. function:: setlogmask(maskpri)
Set the priority mask to *maskpri* and return the previous mask value. Calls to Set the priority mask to *maskpri* and return the previous mask value.
:func:`syslog` with a priority level not set in *maskpri* are ignored. The Calls to :func:`syslog` with a priority level not set in *maskpri*
default is to log all priorities. The function ``LOG_MASK(pri)`` calculates the are ignored. The default is to log all priorities. The function
mask for the individual priority *pri*. The function ``LOG_UPTO(pri)`` ``LOG_MASK(pri)`` calculates the mask for the individual priority
calculates the mask for all priorities up to and including *pri*. *pri*. The function ``LOG_UPTO(pri)`` calculates the mask for all
priorities up to and including *pri*.
The module defines the following constants: The module defines the following constants:
@ -63,3 +87,24 @@ Log options:
:const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, :const:`LOG_NOWAIT` :const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, :const:`LOG_NOWAIT`
and :const:`LOG_PERROR` if defined in ``<syslog.h>``. and :const:`LOG_PERROR` if defined in ``<syslog.h>``.
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...')

View File

@ -329,6 +329,10 @@ C-API
Library 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 - Issue #8108: Fix the unwrap() method of SSL objects when the socket has
a non-infinite timeout. Also make that method friendlier with applications a non-infinite timeout. Also make that method friendlier with applications
wanting to continue using the socket in clear-text mode, by disabling wanting to continue using the socket in clear-text mode, by disabling

View File

@ -26,6 +26,11 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Revision history: 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) 1998/04/28 (Sean Reifschneider)
- When facility not specified to syslog() method, use default from openlog() - When facility not specified to syslog() method, use default from openlog()
(This is how it was claimed to work in the documentation) (This is how it was claimed to work in the documentation)
@ -45,6 +50,7 @@ Revision history:
/* syslog module */ /* syslog module */
#include "Python.h" #include "Python.h"
#include "osdefs.h"
#include <syslog.h> #include <syslog.h>
@ -53,29 +59,82 @@ static PyObject *S_ident_o = NULL; /* identifier, held by openlog() */
static PyObject * static PyObject *
syslog_openlog(PyObject * self, PyObject * args) 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, PyObject *kwds)
{ {
long logopt = 0; long logopt = 0;
long facility = LOG_USER; long facility = LOG_USER;
PyObject *new_S_ident_o; PyObject *new_S_ident_o = NULL;
const char *ident; static char *keywords[] = {"ident", "logoption", "facility", 0};
if (!PyArg_ParseTuple(args, if (!PyArg_ParseTupleAndKeywords(args, kwds,
"U|ll;ident string [, logoption [, facility]]", "|Ull:openlog", keywords, &new_S_ident_o, &logopt, &facility))
&new_S_ident_o, &logopt, &facility))
return NULL; return NULL;
/* This is needed because openlog() does NOT make a copy if (new_S_ident_o) {
* and syslog() later uses it.. cannot trash it. 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); Py_XDECREF(S_ident_o);
S_ident_o = new_S_ident_o; S_ident_o = new_S_ident_o;
Py_INCREF(S_ident_o);
ident = _PyUnicode_AsString(S_ident_o); /* At this point, S_ident_o should be INCREF()ed. openlog(3) does not
if (ident == NULL) * make a copy, and syslog(3) later uses it. We can't garbagecollect it
return NULL; * If NULL, just let openlog figure it out (probably using C argv[0]).
openlog(ident, logopt, facility); */
openlog(S_ident_o ? _PyUnicode_AsString(S_ident_o) : NULL, logopt, facility);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
@ -100,6 +159,22 @@ syslog_syslog(PyObject * self, PyObject * args)
message = _PyUnicode_AsString(message_object); message = _PyUnicode_AsString(message_object);
if (message == NULL) if (message == NULL)
return 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; Py_BEGIN_ALLOW_THREADS;
syslog(priority, "%s", message); syslog(priority, "%s", message);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
@ -152,7 +227,7 @@ syslog_log_upto(PyObject *self, PyObject *args)
/* List of functions defined in the module */ /* List of functions defined in the module */
static PyMethodDef syslog_methods[] = { static PyMethodDef syslog_methods[] = {
{"openlog", syslog_openlog, METH_VARARGS}, {"openlog", (PyCFunction) syslog_openlog, METH_VARARGS | METH_KEYWORDS},
{"closelog", syslog_closelog, METH_NOARGS}, {"closelog", syslog_closelog, METH_NOARGS},
{"syslog", syslog_syslog, METH_VARARGS}, {"syslog", syslog_syslog, METH_VARARGS},
{"setlogmask", syslog_setlogmask, METH_VARARGS}, {"setlogmask", syslog_setlogmask, METH_VARARGS},