Home | History | Annotate | Download | only in Modules
      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"
     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 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;
     72     PyObject *scriptobj;
     73     char *atslash;
     74     PyObject *argv = PySys_GetObject("argv");
     75 
     76     if (argv == NULL) {
     77         return(NULL);
     78     }
     79 
     80     argv_len = PyList_Size(argv);
     81     if (argv_len == -1) {
     82         PyErr_Clear();
     83         return(NULL);
     84     }
     85     if (argv_len == 0) {
     86         return(NULL);
     87     }
     88 
     89     scriptobj = PyList_GetItem(argv, 0);
     90     if (!PyString_Check(scriptobj)) {
     91         return(NULL);
     92     }
     93     if (PyString_GET_SIZE(scriptobj) == 0) {
     94         return(NULL);
     95     }
     96 
     97     atslash = strrchr(PyString_AsString(scriptobj), SEP);
     98     if (atslash) {
     99         return(PyString_FromString(atslash + 1));
    100     } else {
    101         Py_INCREF(scriptobj);
    102         return(scriptobj);
    103     }
    104 
    105     return(NULL);
    106 }
    107 
    108 
    109 static PyObject *
    110 syslog_openlog(PyObject * self, PyObject * args, PyObject *kwds)
    111 {
    112     long logopt = 0;
    113     long facility = LOG_USER;
    114     PyObject *new_S_ident_o = NULL;
    115     static char *keywords[] = {"ident", "logoption", "facility", 0};
    116 
    117     if (!PyArg_ParseTupleAndKeywords(args, kwds,
    118                           "|Sll:openlog", keywords, &new_S_ident_o, &logopt, &facility))
    119         return NULL;
    120 
    121     if (new_S_ident_o) { Py_INCREF(new_S_ident_o); }
    122 
    123     /*  get sys.argv[0] or NULL if we can't for some reason  */
    124     if (!new_S_ident_o) {
    125         new_S_ident_o = syslog_get_argv();
    126         }
    127 
    128     Py_XDECREF(S_ident_o);
    129     S_ident_o = new_S_ident_o;
    130 
    131     /* At this point, S_ident_o should be INCREF()ed.  openlog(3) does not
    132      * make a copy, and syslog(3) later uses it.  We can't garbagecollect it
    133      * If NULL, just let openlog figure it out (probably using C argv[0]).
    134      */
    135 
    136     openlog(S_ident_o ? PyString_AsString(S_ident_o) : NULL, logopt, facility);
    137     S_log_open = 1;
    138 
    139     Py_INCREF(Py_None);
    140     return Py_None;
    141 }
    142 
    143 
    144 static PyObject *
    145 syslog_syslog(PyObject * self, PyObject * args)
    146 {
    147     char *message;
    148     int   priority = LOG_INFO;
    149 
    150     if (!PyArg_ParseTuple(args, "is;[priority,] message string",
    151                           &priority, &message)) {
    152         PyErr_Clear();
    153         if (!PyArg_ParseTuple(args, "s;[priority,] message string",
    154                               &message))
    155             return NULL;
    156     }
    157 
    158     /*  if log is not opened, open it now  */
    159     if (!S_log_open) {
    160         PyObject *openargs;
    161 
    162         /* Continue even if PyTuple_New fails, because openlog(3) is optional.
    163          * So, we can still do loggin in the unlikely event things are so hosed
    164          * that we can't do this tuple.
    165          */
    166         if ((openargs = PyTuple_New(0))) {
    167             PyObject *openlog_ret = syslog_openlog(self, openargs, NULL);
    168             Py_XDECREF(openlog_ret);
    169             Py_DECREF(openargs);
    170         }
    171     }
    172 
    173     Py_BEGIN_ALLOW_THREADS;
    174     syslog(priority, "%s", message);
    175     Py_END_ALLOW_THREADS;
    176     Py_INCREF(Py_None);
    177     return Py_None;
    178 }
    179 
    180 static PyObject *
    181 syslog_closelog(PyObject *self, PyObject *unused)
    182 {
    183     if (S_log_open) {
    184         closelog();
    185         Py_XDECREF(S_ident_o);
    186         S_ident_o = NULL;
    187         S_log_open = 0;
    188     }
    189     Py_INCREF(Py_None);
    190     return Py_None;
    191 }
    192 
    193 static PyObject *
    194 syslog_setlogmask(PyObject *self, PyObject *args)
    195 {
    196     long maskpri, omaskpri;
    197 
    198     if (!PyArg_ParseTuple(args, "l;mask for priority", &maskpri))
    199         return NULL;
    200     omaskpri = setlogmask(maskpri);
    201     return PyInt_FromLong(omaskpri);
    202 }
    203 
    204 static PyObject *
    205 syslog_log_mask(PyObject *self, PyObject *args)
    206 {
    207     long mask;
    208     long pri;
    209     if (!PyArg_ParseTuple(args, "l:LOG_MASK", &pri))
    210         return NULL;
    211     mask = LOG_MASK(pri);
    212     return PyInt_FromLong(mask);
    213 }
    214 
    215 static PyObject *
    216 syslog_log_upto(PyObject *self, PyObject *args)
    217 {
    218     long mask;
    219     long pri;
    220     if (!PyArg_ParseTuple(args, "l:LOG_UPTO", &pri))
    221         return NULL;
    222     mask = LOG_UPTO(pri);
    223     return PyInt_FromLong(mask);
    224 }
    225 
    226 /* List of functions defined in the module */
    227 
    228 static PyMethodDef syslog_methods[] = {
    229     {"openlog",         (PyCFunction) syslog_openlog,           METH_VARARGS | METH_KEYWORDS},
    230     {"closelog",        syslog_closelog,        METH_NOARGS},
    231     {"syslog",          syslog_syslog,          METH_VARARGS},
    232     {"setlogmask",      syslog_setlogmask,      METH_VARARGS},
    233     {"LOG_MASK",        syslog_log_mask,        METH_VARARGS},
    234     {"LOG_UPTO",        syslog_log_upto,        METH_VARARGS},
    235     {NULL,              NULL,                   0}
    236 };
    237 
    238 /* Initialization function for the module */
    239 
    240 PyMODINIT_FUNC
    241 initsyslog(void)
    242 {
    243     PyObject *m;
    244 
    245     /* Create the module and add the functions */
    246     m = Py_InitModule("syslog", syslog_methods);
    247     if (m == NULL)
    248         return;
    249 
    250     /* Add some symbolic constants to the module */
    251 
    252     /* Priorities */
    253     PyModule_AddIntConstant(m, "LOG_EMERG",       LOG_EMERG);
    254     PyModule_AddIntConstant(m, "LOG_ALERT",       LOG_ALERT);
    255     PyModule_AddIntConstant(m, "LOG_CRIT",        LOG_CRIT);
    256     PyModule_AddIntConstant(m, "LOG_ERR",         LOG_ERR);
    257     PyModule_AddIntConstant(m, "LOG_WARNING", LOG_WARNING);
    258     PyModule_AddIntConstant(m, "LOG_NOTICE",  LOG_NOTICE);
    259     PyModule_AddIntConstant(m, "LOG_INFO",        LOG_INFO);
    260     PyModule_AddIntConstant(m, "LOG_DEBUG",       LOG_DEBUG);
    261 
    262     /* openlog() option flags */
    263     PyModule_AddIntConstant(m, "LOG_PID",         LOG_PID);
    264     PyModule_AddIntConstant(m, "LOG_CONS",        LOG_CONS);
    265     PyModule_AddIntConstant(m, "LOG_NDELAY",  LOG_NDELAY);
    266 #ifdef LOG_NOWAIT
    267     PyModule_AddIntConstant(m, "LOG_NOWAIT",  LOG_NOWAIT);
    268 #endif
    269 #ifdef LOG_PERROR
    270     PyModule_AddIntConstant(m, "LOG_PERROR",  LOG_PERROR);
    271 #endif
    272 
    273     /* Facilities */
    274     PyModule_AddIntConstant(m, "LOG_KERN",        LOG_KERN);
    275     PyModule_AddIntConstant(m, "LOG_USER",        LOG_USER);
    276     PyModule_AddIntConstant(m, "LOG_MAIL",        LOG_MAIL);
    277     PyModule_AddIntConstant(m, "LOG_DAEMON",  LOG_DAEMON);
    278     PyModule_AddIntConstant(m, "LOG_AUTH",        LOG_AUTH);
    279     PyModule_AddIntConstant(m, "LOG_LPR",         LOG_LPR);
    280     PyModule_AddIntConstant(m, "LOG_LOCAL0",  LOG_LOCAL0);
    281     PyModule_AddIntConstant(m, "LOG_LOCAL1",  LOG_LOCAL1);
    282     PyModule_AddIntConstant(m, "LOG_LOCAL2",  LOG_LOCAL2);
    283     PyModule_AddIntConstant(m, "LOG_LOCAL3",  LOG_LOCAL3);
    284     PyModule_AddIntConstant(m, "LOG_LOCAL4",  LOG_LOCAL4);
    285     PyModule_AddIntConstant(m, "LOG_LOCAL5",  LOG_LOCAL5);
    286     PyModule_AddIntConstant(m, "LOG_LOCAL6",  LOG_LOCAL6);
    287     PyModule_AddIntConstant(m, "LOG_LOCAL7",  LOG_LOCAL7);
    288 
    289 #ifndef LOG_SYSLOG
    290 #define LOG_SYSLOG              LOG_DAEMON
    291 #endif
    292 #ifndef LOG_NEWS
    293 #define LOG_NEWS                LOG_MAIL
    294 #endif
    295 #ifndef LOG_UUCP
    296 #define LOG_UUCP                LOG_MAIL
    297 #endif
    298 #ifndef LOG_CRON
    299 #define LOG_CRON                LOG_DAEMON
    300 #endif
    301 
    302     PyModule_AddIntConstant(m, "LOG_SYSLOG",  LOG_SYSLOG);
    303     PyModule_AddIntConstant(m, "LOG_CRON",        LOG_CRON);
    304     PyModule_AddIntConstant(m, "LOG_UUCP",        LOG_UUCP);
    305     PyModule_AddIntConstant(m, "LOG_NEWS",        LOG_NEWS);
    306 }
    307