LCOV - code coverage report
Current view: top level - Modules - syslogmodule.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 104 127 81.9 %
Date: 2022-07-20 13:12:14 Functions: 9 9 100.0 %
Branches: 63 120 52.5 %

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

Generated by: LCOV version 1.14