LCOV - code coverage report
Current view: top level - Modules - syslogmodule.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 37 122 30.3 %
Date: 2023-03-20 08:15:36 Functions: 2 10 20.0 %
Branches: 33 112 29.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                 :            : /*[clinic input]
      58                 :            : module syslog
      59                 :            : [clinic start generated code]*/
      60                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=478f4ac94a1d4cae]*/
      61                 :            : 
      62                 :            : #include "clinic/syslogmodule.c.h"
      63                 :            : 
      64                 :            : /*  only one instance, only one syslog, so globals should be ok,
      65                 :            :  *  these fields are writable from the main interpreter only. */
      66                 :            : static PyObject *S_ident_o = NULL;  // identifier, held by openlog()
      67                 :            : static char S_log_open = 0;
      68                 :            : 
      69                 :            : static inline int
      70                 :          0 : is_main_interpreter(void)
      71                 :            : {
      72                 :          0 :     return (PyInterpreterState_Get() == PyInterpreterState_Main());
      73                 :            : }
      74                 :            : 
      75                 :            : static PyObject *
      76                 :          0 : syslog_get_argv(void)
      77                 :            : {
      78                 :            :     /* Figure out what to use for as the program "ident" for openlog().
      79                 :            :      * This swallows exceptions and continues rather than failing out,
      80                 :            :      * because the syslog module can still be used because openlog(3)
      81                 :            :      * is optional.
      82                 :            :      */
      83                 :            : 
      84                 :            :     Py_ssize_t argv_len, scriptlen;
      85                 :            :     PyObject *scriptobj;
      86                 :            :     Py_ssize_t slash;
      87                 :          0 :     PyObject *argv = PySys_GetObject("argv");
      88                 :            : 
      89         [ #  # ]:          0 :     if (argv == NULL) {
      90                 :          0 :         return(NULL);
      91                 :            :     }
      92                 :            : 
      93                 :          0 :     argv_len = PyList_Size(argv);
      94         [ #  # ]:          0 :     if (argv_len == -1) {
      95                 :          0 :         PyErr_Clear();
      96                 :          0 :         return(NULL);
      97                 :            :     }
      98         [ #  # ]:          0 :     if (argv_len == 0) {
      99                 :          0 :         return(NULL);
     100                 :            :     }
     101                 :            : 
     102                 :          0 :     scriptobj = PyList_GetItem(argv, 0);
     103         [ #  # ]:          0 :     if (scriptobj == NULL) {
     104                 :          0 :         PyErr_Clear();
     105                 :          0 :         return NULL;
     106                 :            :     }
     107         [ #  # ]:          0 :     if (!PyUnicode_Check(scriptobj)) {
     108                 :          0 :         return(NULL);
     109                 :            :     }
     110                 :          0 :     scriptlen = PyUnicode_GET_LENGTH(scriptobj);
     111         [ #  # ]:          0 :     if (scriptlen == 0) {
     112                 :          0 :         return(NULL);
     113                 :            :     }
     114                 :            : 
     115                 :          0 :     slash = PyUnicode_FindChar(scriptobj, SEP, 0, scriptlen, -1);
     116         [ #  # ]:          0 :     if (slash == -2) {
     117                 :          0 :         PyErr_Clear();
     118                 :          0 :         return NULL;
     119                 :            :     }
     120         [ #  # ]:          0 :     if (slash != -1) {
     121                 :          0 :         return PyUnicode_Substring(scriptobj, slash + 1, scriptlen);
     122                 :            :     } else {
     123                 :          0 :         Py_INCREF(scriptobj);
     124                 :          0 :         return(scriptobj);
     125                 :            :     }
     126                 :            : }
     127                 :            : 
     128                 :            : 
     129                 :            : /*[clinic input]
     130                 :            : syslog.openlog
     131                 :            : 
     132                 :            :     ident: unicode = NULL
     133                 :            :     logoption as logopt: long = 0
     134                 :            :     facility: long(c_default="LOG_USER") = LOG_USER
     135                 :            : 
     136                 :            : Set logging options of subsequent syslog() calls.
     137                 :            : [clinic start generated code]*/
     138                 :            : 
     139                 :            : static PyObject *
     140                 :          0 : syslog_openlog_impl(PyObject *module, PyObject *ident, long logopt,
     141                 :            :                     long facility)
     142                 :            : /*[clinic end generated code: output=5476c12829b6eb75 input=8a987a96a586eee7]*/
     143                 :            : {
     144                 :            :     // Since the sys.openlog changes the process level state of syslog library,
     145                 :            :     // this operation is only allowed for the main interpreter.
     146         [ #  # ]:          0 :     if (!is_main_interpreter()) {
     147                 :          0 :         PyErr_SetString(PyExc_RuntimeError, "subinterpreter can't use syslog.openlog()");
     148                 :          0 :         return NULL;
     149                 :            :     }
     150                 :            : 
     151                 :          0 :     const char *ident_str = NULL;
     152                 :            : 
     153         [ #  # ]:          0 :     if (ident) {
     154                 :          0 :         Py_INCREF(ident);
     155                 :            :     }
     156                 :            :     else {
     157                 :            :         /* get sys.argv[0] or NULL if we can't for some reason  */
     158                 :          0 :         ident = syslog_get_argv();
     159                 :            :     }
     160                 :            : 
     161                 :            :     /* At this point, ident should be INCREF()ed.  openlog(3) does not
     162                 :            :      * make a copy, and syslog(3) later uses it.  We can't garbagecollect it.
     163                 :            :      * If NULL, just let openlog figure it out (probably using C argv[0]).
     164                 :            :      */
     165         [ #  # ]:          0 :     if (ident) {
     166                 :          0 :         ident_str = PyUnicode_AsUTF8(ident);
     167         [ #  # ]:          0 :         if (ident_str == NULL) {
     168                 :          0 :             Py_DECREF(ident);
     169                 :          0 :             return NULL;
     170                 :            :         }
     171                 :            :     }
     172   [ #  #  #  # ]:          0 :     if (PySys_Audit("syslog.openlog", "Oll", ident ? ident : Py_None, logopt, facility) < 0) {
     173                 :          0 :         Py_DECREF(ident);
     174                 :          0 :         return NULL;
     175                 :            :     }
     176                 :            : 
     177                 :          0 :     openlog(ident_str, logopt, facility);
     178                 :          0 :     S_log_open = 1;
     179                 :          0 :     Py_XSETREF(S_ident_o, ident);
     180                 :            : 
     181                 :          0 :     Py_RETURN_NONE;
     182                 :            : }
     183                 :            : 
     184                 :            : 
     185                 :            : 
     186                 :            : /*[clinic input]
     187                 :            : syslog.syslog
     188                 :            : 
     189                 :            :     [
     190                 :            :     priority: int(c_default="LOG_INFO") = LOG_INFO
     191                 :            :     ]
     192                 :            : 
     193                 :            :     message: str
     194                 :            : 
     195                 :            :     /
     196                 :            : 
     197                 :            : Send the string message to the system logger.
     198                 :            : [clinic start generated code]*/
     199                 :            : 
     200                 :            : static PyObject *
     201                 :          0 : syslog_syslog_impl(PyObject *module, int group_left_1, int priority,
     202                 :            :                    const char *message)
     203                 :            : /*[clinic end generated code: output=c3dbc73445a0e078 input=ac83d92b12ea3d4e]*/
     204                 :            : {
     205         [ #  # ]:          0 :     if (PySys_Audit("syslog.syslog", "is", priority, message) < 0) {
     206                 :          0 :         return NULL;
     207                 :            :     }
     208                 :            : 
     209                 :            :     /*  if log is not opened, open it now  */
     210         [ #  # ]:          0 :     if (!S_log_open) {
     211         [ #  # ]:          0 :         if (!is_main_interpreter()) {
     212                 :          0 :             PyErr_SetString(PyExc_RuntimeError, "subinterpreter can't use syslog.syslog() "
     213                 :            :                                                 "until the syslog is opened by the main interpreter");
     214                 :          0 :             return NULL;
     215                 :            :         }
     216                 :          0 :         PyObject *openlog_ret = syslog_openlog_impl(module, NULL, 0, LOG_USER);
     217         [ #  # ]:          0 :         if (openlog_ret == NULL) {
     218                 :          0 :             return NULL;
     219                 :            :         }
     220                 :          0 :         Py_DECREF(openlog_ret);
     221                 :            :     }
     222                 :            : 
     223                 :            :     /* Incref ident, because it can be decrefed if syslog.openlog() is
     224                 :            :      * called when the GIL is released.
     225                 :            :      */
     226                 :          0 :     PyObject *ident = Py_XNewRef(S_ident_o);
     227                 :            : #ifdef __APPLE__
     228                 :            :     // gh-98178: On macOS, libc syslog() is not thread-safe
     229                 :            :     syslog(priority, "%s", message);
     230                 :            : #else
     231                 :          0 :     Py_BEGIN_ALLOW_THREADS;
     232                 :          0 :     syslog(priority, "%s", message);
     233                 :          0 :     Py_END_ALLOW_THREADS;
     234                 :            : #endif
     235                 :          0 :     Py_XDECREF(ident);
     236                 :          0 :     Py_RETURN_NONE;
     237                 :            : }
     238                 :            : 
     239                 :            : 
     240                 :            : /*[clinic input]
     241                 :            : syslog.closelog
     242                 :            : 
     243                 :            : Reset the syslog module values and call the system library closelog().
     244                 :            : [clinic start generated code]*/
     245                 :            : 
     246                 :            : static PyObject *
     247                 :          0 : syslog_closelog_impl(PyObject *module)
     248                 :            : /*[clinic end generated code: output=97890a80a24b1b84 input=fb77a54d447acf07]*/
     249                 :            : {
     250                 :            :     // Since the sys.closelog changes the process level state of syslog library,
     251                 :            :     // this operation is only allowed for the main interpreter.
     252         [ #  # ]:          0 :     if (!is_main_interpreter()) {
     253                 :          0 :         PyErr_SetString(PyExc_RuntimeError, "sunbinterpreter can't use syslog.closelog()");
     254                 :          0 :         return NULL;
     255                 :            :     }
     256                 :            : 
     257         [ #  # ]:          0 :     if (PySys_Audit("syslog.closelog", NULL) < 0) {
     258                 :          0 :         return NULL;
     259                 :            :     }
     260         [ #  # ]:          0 :     if (S_log_open) {
     261                 :          0 :         closelog();
     262         [ #  # ]:          0 :         Py_CLEAR(S_ident_o);
     263                 :          0 :         S_log_open = 0;
     264                 :            :     }
     265                 :          0 :     Py_RETURN_NONE;
     266                 :            : }
     267                 :            : 
     268                 :            : /*[clinic input]
     269                 :            : syslog.setlogmask -> long
     270                 :            : 
     271                 :            :     maskpri: long
     272                 :            :     /
     273                 :            : 
     274                 :            : Set the priority mask to maskpri and return the previous mask value.
     275                 :            : [clinic start generated code]*/
     276                 :            : 
     277                 :            : static long
     278                 :          0 : syslog_setlogmask_impl(PyObject *module, long maskpri)
     279                 :            : /*[clinic end generated code: output=d6ed163917b434bf input=adff2c2b76c7629c]*/
     280                 :            : {
     281         [ #  # ]:          0 :     if (PySys_Audit("syslog.setlogmask", "l", maskpri) < 0) {
     282                 :          0 :         return -1;
     283                 :            :     }
     284                 :            : 
     285                 :          0 :     return setlogmask(maskpri);
     286                 :            : }
     287                 :            : 
     288                 :            : /*[clinic input]
     289                 :            : syslog.LOG_MASK -> long
     290                 :            : 
     291                 :            :     pri: long
     292                 :            :     /
     293                 :            : 
     294                 :            : Calculates the mask for the individual priority pri.
     295                 :            : [clinic start generated code]*/
     296                 :            : 
     297                 :            : static long
     298                 :          0 : syslog_LOG_MASK_impl(PyObject *module, long pri)
     299                 :            : /*[clinic end generated code: output=c4a5bbfcc74c7c94 input=534829cb7fb5f7d2]*/
     300                 :            : {
     301                 :          0 :     return LOG_MASK(pri);
     302                 :            : }
     303                 :            : 
     304                 :            : /*[clinic input]
     305                 :            : syslog.LOG_UPTO -> long
     306                 :            : 
     307                 :            :     pri: long
     308                 :            :     /
     309                 :            : 
     310                 :            : Calculates the mask for all priorities up to and including pri.
     311                 :            : [clinic start generated code]*/
     312                 :            : 
     313                 :            : static long
     314                 :          0 : syslog_LOG_UPTO_impl(PyObject *module, long pri)
     315                 :            : /*[clinic end generated code: output=9eab083c90601d7e input=5e906d6c406b7458]*/
     316                 :            : {
     317                 :          0 :     return LOG_UPTO(pri);
     318                 :            : }
     319                 :            : 
     320                 :            : /* List of functions defined in the module */
     321                 :            : 
     322                 :            : static PyMethodDef syslog_methods[] = {
     323                 :            :     SYSLOG_OPENLOG_METHODDEF
     324                 :            :     SYSLOG_CLOSELOG_METHODDEF
     325                 :            :     SYSLOG_SYSLOG_METHODDEF
     326                 :            :     SYSLOG_SETLOGMASK_METHODDEF
     327                 :            :     SYSLOG_LOG_MASK_METHODDEF
     328                 :            :     SYSLOG_LOG_UPTO_METHODDEF
     329                 :            :     {NULL,              NULL,                   0}
     330                 :            : };
     331                 :            : 
     332                 :            : 
     333                 :            : static int
     334                 :          1 : syslog_exec(PyObject *module)
     335                 :            : {
     336                 :            : #define ADD_INT_MACRO(module, macro)                                  \
     337                 :            :     do {                                                              \
     338                 :            :         if (PyModule_AddIntConstant(module, #macro, macro) < 0) {     \
     339                 :            :             return -1;                                                \
     340                 :            :         }                                                             \
     341                 :            :     } while (0)
     342                 :            :     /* Priorities */
     343         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_EMERG);
     344         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_ALERT);
     345         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_CRIT);
     346         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_ERR);
     347         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_WARNING);
     348         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_NOTICE);
     349         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_INFO);
     350         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_DEBUG);
     351                 :            : 
     352                 :            :     /* openlog() option flags */
     353         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_PID);
     354         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_CONS);
     355         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_NDELAY);
     356                 :            : #ifdef LOG_ODELAY
     357         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_ODELAY);
     358                 :            : #endif
     359                 :            : #ifdef LOG_NOWAIT
     360         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_NOWAIT);
     361                 :            : #endif
     362                 :            : #ifdef LOG_PERROR
     363         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_PERROR);
     364                 :            : #endif
     365                 :            : 
     366                 :            :     /* Facilities */
     367         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_KERN);
     368         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_USER);
     369         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_MAIL);
     370         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_DAEMON);
     371         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_AUTH);
     372         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LPR);
     373         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LOCAL0);
     374         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LOCAL1);
     375         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LOCAL2);
     376         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LOCAL3);
     377         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LOCAL4);
     378         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LOCAL5);
     379         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LOCAL6);
     380         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_LOCAL7);
     381                 :            : 
     382                 :            : #ifndef LOG_SYSLOG
     383                 :            : #define LOG_SYSLOG              LOG_DAEMON
     384                 :            : #endif
     385                 :            : #ifndef LOG_NEWS
     386                 :            : #define LOG_NEWS                LOG_MAIL
     387                 :            : #endif
     388                 :            : #ifndef LOG_UUCP
     389                 :            : #define LOG_UUCP                LOG_MAIL
     390                 :            : #endif
     391                 :            : #ifndef LOG_CRON
     392                 :            : #define LOG_CRON                LOG_DAEMON
     393                 :            : #endif
     394                 :            : 
     395         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_SYSLOG);
     396         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_CRON);
     397         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_UUCP);
     398         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_NEWS);
     399                 :            : 
     400                 :            : #ifdef LOG_AUTHPRIV
     401         [ -  + ]:          1 :     ADD_INT_MACRO(module, LOG_AUTHPRIV);
     402                 :            : #endif
     403                 :            : 
     404                 :          1 :     return 0;
     405                 :            : }
     406                 :            : 
     407                 :            : static PyModuleDef_Slot syslog_slots[] = {
     408                 :            :     {Py_mod_exec, syslog_exec},
     409                 :            :     {0, NULL}
     410                 :            : };
     411                 :            : 
     412                 :            : /* Initialization function for the module */
     413                 :            : 
     414                 :            : static struct PyModuleDef syslogmodule = {
     415                 :            :     PyModuleDef_HEAD_INIT,
     416                 :            :     .m_name = "syslog",
     417                 :            :     .m_size = 0,
     418                 :            :     .m_methods = syslog_methods,
     419                 :            :     .m_slots = syslog_slots,
     420                 :            : };
     421                 :            : 
     422                 :            : PyMODINIT_FUNC
     423                 :          1 : PyInit_syslog(void)
     424                 :            : {
     425                 :          1 :     return PyModuleDef_Init(&syslogmodule);
     426                 :            : }

Generated by: LCOV version 1.14