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