LCOV - code coverage report
Current view: top level - Modules - syslogmodule.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 104 127 81.9 %
Date: 2022-07-07 18:19:46 Functions: 9 9 100.0 %

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

Generated by: LCOV version 1.14