Code

pyvalues.c: remove unneccesary semicolon
[collectd.git] / src / python.c
1 /**
2  * collectd - src/python.c
3  * Copyright (C) 2009  Sven Trenkel
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Sven Trenkel <collectd at semidefinite.de>
25  **/
27 #include <Python.h>
28 #include <structmember.h>
30 #include <signal.h>
31 #if HAVE_PTHREAD_H
32 # include <pthread.h>
33 #endif
35 #include "collectd.h"
36 #include "common.h"
38 #include "cpython.h"
40 typedef struct cpy_callback_s {
41         char *name;
42         PyObject *callback;
43         PyObject *data;
44         struct cpy_callback_s *next;
45 } cpy_callback_t;
47 static char log_doc[] = "This function sends a string to all logging plugins.";
49 static char get_ds_doc[] = "get_dataset(name) -> definition\n"
50                 "\n"
51                 "Returns the definition of a dataset specified by name.\n"
52                 "\n"
53                 "'name' is a string specifying the dataset to query.\n"
54                 "'definition' is a list of 4-tuples. Every tuple represents a \n"
55                 "    data source within the data set and its 4 values are the \n"
56                 "    name, type, min and max value.\n"
57                 "    'name' is a string.\n"
58                 "    'type' is a string that is equal to either DS_TYPE_COUNTER,\n"
59                 "        DS_TYPE_GAUGE, DS_TYPE_DERIVE or DS_TYPE_ABSOLUTE.\n"
60                 "    'min' and 'max' are either a float or None.";
62 static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
63                 "\n"
64                 "Flushes the cache of another plugin.";
66 static char unregister_doc[] = "Unregisters a callback. This function needs exactly one parameter either\n"
67                 "the function to unregister or the callback identifier to unregister.";
69 static char reg_log_doc[] = "register_log(callback[, data][, name]) -> identifier\n"
70                 "\n"
71                 "Register a callback function for log messages.\n"
72                 "\n"
73                 "'callback' is a callable object that will be called every time something\n"
74                 "    is logged.\n"
75                 "'data' is an optional object that will be passed back to the callback\n"
76                 "    function every time it is called.\n"
77                 "'name' is an optional identifier for this callback. The default name\n"
78                 "    is 'python.<module>'.\n"
79                 "    Every callback needs a unique identifier, so if you want to\n"
80                 "    register this callback multiple time from the same module you need\n"
81                 "    to specify a name here.\n"
82                 "'identifier' is the full identifier assigned to this callback.\n"
83                 "\n"
84                 "The callback function will be called with two or three parameters:\n"
85                 "severity: An integer that should be compared to the LOG_ constants.\n"
86                 "message: The text to be logged.\n"
87                 "data: The optional data parameter passed to the register function.\n"
88                 "    If the parameter was omitted it will be omitted here, too.";
90 static char reg_init_doc[] = "register_init(callback[, data][, name]) -> identifier\n"
91                 "\n"
92                 "Register a callback function that will be executed once after the config.\n"
93                 "file has been read, all plugins heve been loaded and the collectd has\n"
94                 "forked into the background.\n"
95                 "\n"
96                 "'callback' is a callable object that will be executed.\n"
97                 "'data' is an optional object that will be passed back to the callback\n"
98                 "    function when it is called.\n"
99                 "'name' is an optional identifier for this callback. The default name\n"
100                 "    is 'python.<module>'.\n"
101                 "    Every callback needs a unique identifier, so if you want to\n"
102                 "    register this callback multiple time from the same module you need\n"
103                 "    to specify a name here.\n"
104                 "'identifier' is the full identifier assigned to this callback.\n"
105                 "\n"
106                 "The callback function will be called without parameters, except for\n"
107                 "data if it was supplied.";
109 static char reg_config_doc[] = "register_config(callback[, data][, name]) -> identifier\n"
110                 "\n"
111                 "Register a callback function for config file entries.\n"
112                 "'callback' is a callable object that will be called for every config block.\n"
113                 "'data' is an optional object that will be passed back to the callback\n"
114                 "    function every time it is called.\n"
115                 "'name' is an optional identifier for this callback. The default name\n"
116                 "    is 'python.<module>'.\n"
117                 "    Every callback needs a unique identifier, so if you want to\n"
118                 "    register this callback multiple time from the same module you need\n"
119                 "    to specify a name here.\n"
120                 "'identifier' is the full identifier assigned to this callback.\n"
121                 "\n"
122                 "The callback function will be called with one or two parameters:\n"
123                 "config: A Config object.\n"
124                 "data: The optional data parameter passed to the register function.\n"
125                 "    If the parameter was omitted it will be omitted here, too.";
127 static char reg_read_doc[] = "register_read(callback[, interval][, data][, name]) -> identifier\n"
128                 "\n"
129                 "Register a callback function for reading data. It will just be called\n"
130                 "in a fixed interval to signal that it's time to dispatch new values.\n"
131                 "'callback' is a callable object that will be called every time something\n"
132                 "    is logged.\n"
133                 "'interval' is the number of seconds between between calls to the callback\n"
134                 "    function. Full float precision is supported here.\n"
135                 "'data' is an optional object that will be passed back to the callback\n"
136                 "    function every time it is called.\n"
137                 "'name' is an optional identifier for this callback. The default name\n"
138                 "    is 'python.<module>'.\n"
139                 "    Every callback needs a unique identifier, so if you want to\n"
140                 "    register this callback multiple time from the same module you need\n"
141                 "    to specify a name here.\n"
142                 "'identifier' is the full identifier assigned to this callback.\n"
143                 "\n"
144                 "The callback function will be called without parameters, except for\n"
145                 "data if it was supplied.";
147 static char reg_write_doc[] = "register_write(callback[, data][, name]) -> identifier\n"
148                 "\n"
149                 "Register a callback function to receive values dispatched by other plugins.\n"
150                 "'callback' is a callable object that will be called every time a value\n"
151                 "    is dispatched.\n"
152                 "'data' is an optional object that will be passed back to the callback\n"
153                 "    function every time it is called.\n"
154                 "'name' is an optional identifier for this callback. The default name\n"
155                 "    is 'python.<module>'.\n"
156                 "    Every callback needs a unique identifier, so if you want to\n"
157                 "    register this callback multiple time from the same module you need\n"
158                 "    to specify a name here.\n"
159                 "'identifier' is the full identifier assigned to this callback.\n"
160                 "\n"
161                 "The callback function will be called with one or two parameters:\n"
162                 "values: A Values object which is a copy of the dispatched values.\n"
163                 "data: The optional data parameter passed to the register function.\n"
164                 "    If the parameter was omitted it will be omitted here, too.";
166 static char reg_notification_doc[] = "register_notification(callback[, data][, name]) -> identifier\n"
167                 "\n"
168                 "Register a callback function for notifications.\n"
169                 "'callback' is a callable object that will be called every time a notification\n"
170                 "    is dispatched.\n"
171                 "'data' is an optional object that will be passed back to the callback\n"
172                 "    function every time it is called.\n"
173                 "'name' is an optional identifier for this callback. The default name\n"
174                 "    is 'python.<module>'.\n"
175                 "    Every callback needs a unique identifier, so if you want to\n"
176                 "    register this callback multiple time from the same module you need\n"
177                 "    to specify a name here.\n"
178                 "'identifier' is the full identifier assigned to this callback.\n"
179                 "\n"
180                 "The callback function will be called with one or two parameters:\n"
181                 "notification: A copy of the notification that was dispatched.\n"
182                 "data: The optional data parameter passed to the register function.\n"
183                 "    If the parameter was omitted it will be omitted here, too.";
185 static char reg_flush_doc[] = "register_flush(callback[, data][, name]) -> identifier\n"
186                 "\n"
187                 "Register a callback function for flush messages.\n"
188                 "'callback' is a callable object that will be called every time a plugin\n"
189                 "    requests a flush for either this or all plugins.\n"
190                 "'data' is an optional object that will be passed back to the callback\n"
191                 "    function every time it is called.\n"
192                 "'name' is an optional identifier for this callback. The default name\n"
193                 "    is 'python.<module>'.\n"
194                 "    Every callback needs a unique identifier, so if you want to\n"
195                 "    register this callback multiple time from the same module you need\n"
196                 "    to specify a name here.\n"
197                 "'identifier' is the full identifier assigned to this callback.\n"
198                 "\n"
199                 "The callback function will be called with two or three parameters:\n"
200                 "timeout: Indicates that only data older than 'timeout' seconds is to\n"
201                 "    be flushed.\n"
202                 "id: Specifies which values are to be flushed.\n"
203                 "data: The optional data parameter passed to the register function.\n"
204                 "    If the parameter was omitted it will be omitted here, too.";
206 static char reg_shutdown_doc[] = "register_shutdown(callback[, data][, name]) -> identifier\n"
207                 "\n"
208                 "Register a callback function for collectd shutdown.\n"
209                 "'callback' is a callable object that will be called once collectd is\n"
210                 "    shutting down.\n"
211                 "'data' is an optional object that will be passed back to the callback\n"
212                 "    function if it is called.\n"
213                 "'name' is an optional identifier for this callback. The default name\n"
214                 "    is 'python.<module>'.\n"
215                 "    Every callback needs a unique identifier, so if you want to\n"
216                 "    register this callback multiple time from the same module you need\n"
217                 "    to specify a name here.\n"
218                 "'identifier' is the full identifier assigned to this callback.\n"
219                 "\n"
220                 "The callback function will be called with no parameters except for\n"
221                 "    data if it was supplied.";
224 static int do_interactive = 0;
226 /* This is our global thread state. Python saves some stuff in thread-local
227  * storage. So if we allow the interpreter to run in the background
228  * (the scriptwriters might have created some threads from python), we have
229  * to save the state so we can resume it later after shutdown. */
231 static PyThreadState *state;
233 static PyObject *sys_path, *cpy_format_exception;
235 static cpy_callback_t *cpy_config_callbacks;
236 static cpy_callback_t *cpy_init_callbacks;
237 static cpy_callback_t *cpy_shutdown_callbacks;
239 static void cpy_destroy_user_data(void *data) {
240         cpy_callback_t *c = data;
241         free(c->name);
242         Py_DECREF(c->callback);
243         Py_XDECREF(c->data);
244         free(c);
247 /* You must hold the GIL to call this function!
248  * But if you managed to extract the callback parameter then you probably already do. */
250 static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) {
251         const char *module = NULL;
252         PyObject *mod = NULL;
254         if (name != NULL) {
255                 snprintf(buf, size, "python.%s", name);
256                 return;
257         }
259         mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
260         if (mod != NULL)
261                 module = cpy_unicode_or_bytes_to_string(&mod);
263         if (module != NULL) {
264                 snprintf(buf, size, "python.%s", module);
265                 Py_XDECREF(mod);
266                 PyErr_Clear();
267                 return;
268         }
269         Py_XDECREF(mod);
271         snprintf(buf, size, "python.%p", callback);
272         PyErr_Clear();
275 void cpy_log_exception(const char *context) {
276         int l = 0, i;
277         const char *typename = NULL, *message = NULL;
278         PyObject *type, *value, *traceback, *tn, *m, *list;
280         PyErr_Fetch(&type, &value, &traceback);
281         PyErr_NormalizeException(&type, &value, &traceback);
282         if (type == NULL) return;
283         tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
284         m = PyObject_Str(value); /* New reference. */
285         if (tn != NULL)
286                 typename = cpy_unicode_or_bytes_to_string(&tn);
287         if (m != NULL)
288                 message = cpy_unicode_or_bytes_to_string(&m);
289         if (typename == NULL)
290                 typename = "NamelessException";
291         if (message == NULL)
292                 message = "N/A";
293         Py_BEGIN_ALLOW_THREADS
294         ERROR("Unhandled python exception in %s: %s: %s", context, typename, message);
295         Py_END_ALLOW_THREADS
296         Py_XDECREF(tn);
297         Py_XDECREF(m);
298         if (!cpy_format_exception || !traceback) {
299                 PyErr_Clear();
300                 Py_DECREF(type);
301                 Py_XDECREF(value);
302                 Py_XDECREF(traceback);
303                 return;
304         }
305         list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. Steals references from "type", "value" and "traceback". */
306         if (list)
307                 l = PyObject_Length(list);
309         for (i = 0; i < l; ++i) {
310                 PyObject *line;
311                 char const *msg;
312                 char *cpy;
314                 line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
315                 Py_INCREF(line);
317                 msg = cpy_unicode_or_bytes_to_string(&line);
318                 Py_DECREF(line);
319                 if (msg == NULL)
320                         continue;
322                 cpy = strdup(msg);
323                 if (cpy == NULL)
324                         continue;
326                 if (cpy[strlen(cpy) - 1] == '\n')
327                         cpy[strlen(cpy) - 1] = 0;
329                 Py_BEGIN_ALLOW_THREADS
330                 ERROR("%s", cpy);
331                 Py_END_ALLOW_THREADS
333                 free(cpy);
334         }
336         Py_XDECREF(list);
337         PyErr_Clear();
340 static int cpy_read_callback(user_data_t *data) {
341         cpy_callback_t *c = data->data;
342         PyObject *ret;
344         CPY_LOCK_THREADS
345                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
346                 if (ret == NULL) {
347                         cpy_log_exception("read callback");
348                 } else {
349                         Py_DECREF(ret);
350                 }
351         CPY_RELEASE_THREADS
352         if (ret == NULL)
353                 return 1;
354         return 0;
357 static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
358         size_t i;
359         cpy_callback_t *c = data->data;
360         PyObject *ret, *list, *temp, *dict = NULL;
361         Values *v;
363         CPY_LOCK_THREADS
364                 list = PyList_New(value_list->values_len); /* New reference. */
365                 if (list == NULL) {
366                         cpy_log_exception("write callback");
367                         CPY_RETURN_FROM_THREADS 0;
368                 }
369                 for (i = 0; i < value_list->values_len; ++i) {
370                         if (ds->ds[i].type == DS_TYPE_COUNTER) {
371                                 PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
372                         } else if (ds->ds[i].type == DS_TYPE_GAUGE) {
373                                 PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
374                         } else if (ds->ds[i].type == DS_TYPE_DERIVE) {
375                                 PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
376                         } else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
377                                 PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
378                         } else {
379                                 Py_BEGIN_ALLOW_THREADS
380                                 ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
381                                 Py_END_ALLOW_THREADS
382                                 Py_DECREF(list);
383                                 CPY_RETURN_FROM_THREADS 0;
384                         }
385                         if (PyErr_Occurred() != NULL) {
386                                 cpy_log_exception("value building for write callback");
387                                 Py_DECREF(list);
388                                 CPY_RETURN_FROM_THREADS 0;
389                         }
390                 }
391                 dict = PyDict_New();  /* New reference. */
392                 if (value_list->meta) {
393                         int num;
394                         char **table;
395                         meta_data_t *meta = value_list->meta;
397                         num = meta_data_toc(meta, &table);
398                         for (i = 0; i < num; ++i) {
399                                 int type;
400                                 char *string;
401                                 int64_t si;
402                                 uint64_t ui;
403                                 double d;
404                                 _Bool b;
406                                 type = meta_data_type(meta, table[i]);
407                                 if (type == MD_TYPE_STRING) {
408                                         if (meta_data_get_string(meta, table[i], &string))
409                                                 continue;
410                                         temp = cpy_string_to_unicode_or_bytes(string);  /* New reference. */
411                                         free(string);
412                                         PyDict_SetItemString(dict, table[i], temp);
413                                         Py_XDECREF(temp);
414                                 } else if (type == MD_TYPE_SIGNED_INT) {
415                                         if (meta_data_get_signed_int(meta, table[i], &si))
416                                                 continue;
417                                         temp = PyObject_CallFunctionObjArgs((void *) &SignedType, PyLong_FromLongLong(si), (void *) 0);  /* New reference. */
418                                         PyDict_SetItemString(dict, table[i], temp);
419                                         Py_XDECREF(temp);
420                                 } else if (type == MD_TYPE_UNSIGNED_INT) {
421                                         if (meta_data_get_unsigned_int(meta, table[i], &ui))
422                                                 continue;
423                                         temp = PyObject_CallFunctionObjArgs((void *) &UnsignedType, PyLong_FromUnsignedLongLong(ui), (void *) 0);  /* New reference. */
424                                         PyDict_SetItemString(dict, table[i], temp);
425                                         Py_XDECREF(temp);
426                                 } else if (type == MD_TYPE_DOUBLE) {
427                                         if (meta_data_get_double(meta, table[i], &d))
428                                                 continue;
429                                         temp = PyFloat_FromDouble(d);  /* New reference. */
430                                         PyDict_SetItemString(dict, table[i], temp);
431                                         Py_XDECREF(temp);
432                                 } else if (type == MD_TYPE_BOOLEAN) {
433                                         if (meta_data_get_boolean(meta, table[i], &b))
434                                                 continue;
435                                         if (b)
436                                                 PyDict_SetItemString(dict, table[i], Py_True);
437                                         else
438                                                 PyDict_SetItemString(dict, table[i], Py_False);
439                                 }
440                                 free(table[i]);
441                         }
442                         free(table);
443                 }
444                 v = (Values *) Values_New(); /* New reference. */
445                 sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
446                 sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
447                 sstrncpy(v->data.type_instance, value_list->type_instance, sizeof(v->data.type_instance));
448                 sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
449                 sstrncpy(v->data.plugin_instance, value_list->plugin_instance, sizeof(v->data.plugin_instance));
450                 v->data.time = CDTIME_T_TO_DOUBLE(value_list->time);
451                 v->interval = CDTIME_T_TO_DOUBLE(value_list->interval);
452                 Py_CLEAR(v->values);
453                 v->values = list;
454                 Py_CLEAR(v->meta);
455                 v->meta = dict;  /* Steals a reference. */
456                 ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
457                 Py_XDECREF(v);
458                 if (ret == NULL) {
459                         cpy_log_exception("write callback");
460                 } else {
461                         Py_DECREF(ret);
462                 }
463         CPY_RELEASE_THREADS
464         return 0;
467 static int cpy_notification_callback(const notification_t *notification, user_data_t *data) {
468         cpy_callback_t *c = data->data;
469         PyObject *ret, *notify;
470         Notification *n;
472         CPY_LOCK_THREADS
473                 notify = Notification_New(); /* New reference. */
474                 n = (Notification *) notify;
475                 sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
476                 sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
477                 sstrncpy(n->data.type_instance, notification->type_instance, sizeof(n->data.type_instance));
478                 sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
479                 sstrncpy(n->data.plugin_instance, notification->plugin_instance, sizeof(n->data.plugin_instance));
480                 n->data.time = CDTIME_T_TO_DOUBLE(notification->time);
481                 sstrncpy(n->message, notification->message, sizeof(n->message));
482                 n->severity = notification->severity;
483                 ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
484                 Py_XDECREF(notify);
485                 if (ret == NULL) {
486                         cpy_log_exception("notification callback");
487                 } else {
488                         Py_DECREF(ret);
489                 }
490         CPY_RELEASE_THREADS
491         return 0;
494 static void cpy_log_callback(int severity, const char *message, user_data_t *data) {
495         cpy_callback_t * c = data->data;
496         PyObject *ret, *text;
498         CPY_LOCK_THREADS
499         text = cpy_string_to_unicode_or_bytes(message);  /* New reference. */
500         if (c->data == NULL)
501                 ret = PyObject_CallFunction(c->callback, "iN", severity, text); /* New reference. Steals a reference from "text". */
502         else
503                 ret = PyObject_CallFunction(c->callback, "iNO", severity, text, c->data); /* New reference. Steals a reference from "text". */
505         if (ret == NULL) {
506                 /* FIXME */
507                 /* Do we really want to trigger a log callback because a log callback failed?
508                  * Probably not. */
509                 PyErr_Print();
510                 /* In case someone wanted to be clever, replaced stderr and failed at that. */
511                 PyErr_Clear();
512         } else {
513                 Py_DECREF(ret);
514         }
515         CPY_RELEASE_THREADS
518 static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
519         cpy_callback_t * c = data->data;
520         PyObject *ret, *text;
522         CPY_LOCK_THREADS
523         text = cpy_string_to_unicode_or_bytes(id);
524         if (c->data == NULL)
525                 ret = PyObject_CallFunction(c->callback, "iN", timeout, text); /* New reference. */
526         else
527                 ret = PyObject_CallFunction(c->callback, "iNO", timeout, text, c->data); /* New reference. */
529         if (ret == NULL) {
530                 cpy_log_exception("flush callback");
531         } else {
532                 Py_DECREF(ret);
533         }
534         CPY_RELEASE_THREADS
537 static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
538         char buf[512];
539         cpy_callback_t *c;
540         char *name = NULL;
541         PyObject *callback = NULL, *data = NULL, *mod = NULL;
542         static char *kwlist[] = {"callback", "data", "name", NULL};
544         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
545         if (PyCallable_Check(callback) == 0) {
546                 PyMem_Free(name);
547                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
548                 return NULL;
549         }
550         cpy_build_name(buf, sizeof(buf), callback, name);
552         Py_INCREF(callback);
553         Py_XINCREF(data);
555         c = calloc(1, sizeof(*c));
556         if (c == NULL)
557                 return NULL;
559         c->name = strdup(buf);
560         c->callback = callback;
561         c->data = data;
562         c->next = *list_head;
563         *list_head = c;
564         Py_XDECREF(mod);
565         PyMem_Free(name);
566         return cpy_string_to_unicode_or_bytes(buf);
569 static PyObject *float_or_none(float number) {
570         if (isnan(number)) {
571                 Py_RETURN_NONE;
572         }
573         return PyFloat_FromDouble(number);
576 static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
577         size_t i;
578         char *name;
579         const data_set_t *ds;
580         PyObject *list, *tuple;
582         if (PyArg_ParseTuple(args, "et", NULL, &name) == 0) return NULL;
583         ds = plugin_get_ds(name);
584         PyMem_Free(name);
585         if (ds == NULL) {
586                 PyErr_Format(PyExc_TypeError, "Dataset %s not found", name);
587                 return NULL;
588         }
589         list = PyList_New(ds->ds_num); /* New reference. */
590         for (i = 0; i < ds->ds_num; ++i) {
591                 tuple = PyTuple_New(4);
592                 PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
593                 PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
594                 PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min));
595                 PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max));
596                 PyList_SET_ITEM(list, i, tuple);
597         }
598         return list;
601 static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
602         int timeout = -1;
603         char *plugin = NULL, *identifier = NULL;
604         static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
606         if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
607         Py_BEGIN_ALLOW_THREADS
608         plugin_flush(plugin, timeout, identifier);
609         Py_END_ALLOW_THREADS
610         PyMem_Free(plugin);
611         PyMem_Free(identifier);
612         Py_RETURN_NONE;
615 static PyObject *cpy_register_config(PyObject *self, PyObject *args, PyObject *kwds) {
616         return cpy_register_generic(&cpy_config_callbacks, args, kwds);
619 static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwds) {
620         return cpy_register_generic(&cpy_init_callbacks, args, kwds);
623 typedef int reg_function_t(const char *name, void *callback, void *data);
625 static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) {
626         char buf[512];
627         reg_function_t *register_function = (reg_function_t *) reg;
628         cpy_callback_t *c = NULL;
629         user_data_t user_data;
630         char *name = NULL;
631         PyObject *callback = NULL, *data = NULL;
632         static char *kwlist[] = {"callback", "data", "name", NULL};
634         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
635         if (PyCallable_Check(callback) == 0) {
636                 PyMem_Free(name);
637                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
638                 return NULL;
639         }
640         cpy_build_name(buf, sizeof(buf), callback, name);
641         PyMem_Free(name);
643         Py_INCREF(callback);
644         Py_XINCREF(data);
646         c = calloc(1, sizeof(*c));
647         if (c == NULL)
648                 return NULL;
650         c->name = strdup(buf);
651         c->callback = callback;
652         c->data = data;
653         c->next = NULL;
655         memset (&user_data, 0, sizeof (user_data));
656         user_data.free_func = cpy_destroy_user_data;
657         user_data.data = c;
659         register_function(buf, handler, &user_data);
660         return cpy_string_to_unicode_or_bytes(buf);
663 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
664         char buf[512];
665         cpy_callback_t *c = NULL;
666         user_data_t user_data;
667         double interval = 0;
668         char *name = NULL;
669         PyObject *callback = NULL, *data = NULL;
670         static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
672         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
673         if (PyCallable_Check(callback) == 0) {
674                 PyMem_Free(name);
675                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
676                 return NULL;
677         }
678         cpy_build_name(buf, sizeof(buf), callback, name);
679         PyMem_Free(name);
681         Py_INCREF(callback);
682         Py_XINCREF(data);
684         c = calloc(1, sizeof(*c));
685         if (c == NULL)
686                 return NULL;
688         c->name = strdup(buf);
689         c->callback = callback;
690         c->data = data;
691         c->next = NULL;
693         memset (&user_data, 0, sizeof (user_data));
694         user_data.free_func = cpy_destroy_user_data;
695         user_data.data = c;
697         plugin_register_complex_read(/* group = */ "python", buf,
698                         cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
699         return cpy_string_to_unicode_or_bytes(buf);
702 static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
703         return cpy_register_generic_userdata((void *) plugin_register_log,
704                         (void *) cpy_log_callback, args, kwds);
707 static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) {
708         return cpy_register_generic_userdata((void *) plugin_register_write,
709                         (void *) cpy_write_callback, args, kwds);
712 static PyObject *cpy_register_notification(PyObject *self, PyObject *args, PyObject *kwds) {
713         return cpy_register_generic_userdata((void *) plugin_register_notification,
714                         (void *) cpy_notification_callback, args, kwds);
717 static PyObject *cpy_register_flush(PyObject *self, PyObject *args, PyObject *kwds) {
718         return cpy_register_generic_userdata((void *) plugin_register_flush,
719                         (void *) cpy_flush_callback, args, kwds);
722 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) {
723         return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
726 static PyObject *cpy_error(PyObject *self, PyObject *args) {
727         char *text;
728         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
729         Py_BEGIN_ALLOW_THREADS
730         plugin_log(LOG_ERR, "%s", text);
731         Py_END_ALLOW_THREADS
732         PyMem_Free(text);
733         Py_RETURN_NONE;
736 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
737         char *text;
738         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
739         Py_BEGIN_ALLOW_THREADS
740         plugin_log(LOG_WARNING, "%s", text);
741         Py_END_ALLOW_THREADS
742         PyMem_Free(text);
743         Py_RETURN_NONE;
746 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
747         char *text;
748         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
749         Py_BEGIN_ALLOW_THREADS
750         plugin_log(LOG_NOTICE, "%s", text);
751         Py_END_ALLOW_THREADS
752         PyMem_Free(text);
753         Py_RETURN_NONE;
756 static PyObject *cpy_info(PyObject *self, PyObject *args) {
757         char *text;
758         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
759         Py_BEGIN_ALLOW_THREADS
760         plugin_log(LOG_INFO, "%s", text);
761         Py_END_ALLOW_THREADS
762         PyMem_Free(text);
763         Py_RETURN_NONE;
766 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
767 #ifdef COLLECT_DEBUG
768         char *text;
769         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
770         Py_BEGIN_ALLOW_THREADS
771         plugin_log(LOG_DEBUG, "%s", text);
772         Py_END_ALLOW_THREADS
773         PyMem_Free(text);
774 #endif
775         Py_RETURN_NONE;
778 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *arg, const char *desc) {
779         char buf[512];
780         const char *name;
781         cpy_callback_t *prev = NULL, *tmp;
783         Py_INCREF(arg);
784         name = cpy_unicode_or_bytes_to_string(&arg);
785         if (name == NULL) {
786                 PyErr_Clear();
787                 if (!PyCallable_Check(arg)) {
788                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
789                         Py_DECREF(arg);
790                         return NULL;
791                 }
792                 cpy_build_name(buf, sizeof(buf), arg, NULL);
793                 name = buf;
794         }
795         for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
796                 if (strcmp(name, tmp->name) == 0)
797                         break;
799         Py_DECREF(arg);
800         if (tmp == NULL) {
801                 PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
802                 return NULL;
803         }
804         /* Yes, this is actually save. To call this function the caller has to
805          * hold the GIL. Well, save as long as there is only one GIL anyway ... */
806         if (prev == NULL)
807                 *list_head = tmp->next;
808         else
809                 prev->next = tmp->next;
810         cpy_destroy_user_data(tmp);
811         Py_RETURN_NONE;
814 typedef int cpy_unregister_function_t(const char *name);
816 static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
817         char buf[512];
818         const char *name;
820         Py_INCREF(arg);
821         name = cpy_unicode_or_bytes_to_string(&arg);
822         if (name == NULL) {
823                 PyErr_Clear();
824                 if (!PyCallable_Check(arg)) {
825                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
826                         Py_DECREF(arg);
827                         return NULL;
828                 }
829                 cpy_build_name(buf, sizeof(buf), arg, NULL);
830                 name = buf;
831         }
832         if (unreg(name) == 0) {
833                 Py_DECREF(arg);
834                 Py_RETURN_NONE;
835         }
836         PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
837         Py_DECREF(arg);
838         return NULL;
841 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
842         return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
845 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
846         return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
849 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
850         return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
853 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
854         return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
857 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
858         return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
861 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
862         return cpy_unregister_generic_userdata(plugin_unregister_notification, arg, "notification");
865 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
866         return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
869 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
870         return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
873 static PyMethodDef cpy_methods[] = {
874         {"debug", cpy_debug, METH_VARARGS, log_doc},
875         {"info", cpy_info, METH_VARARGS, log_doc},
876         {"notice", cpy_notice, METH_VARARGS, log_doc},
877         {"warning", cpy_warning, METH_VARARGS, log_doc},
878         {"error", cpy_error, METH_VARARGS, log_doc},
879         {"get_dataset", (PyCFunction) cpy_get_dataset, METH_VARARGS, get_ds_doc},
880         {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
881         {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
882         {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
883         {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, reg_config_doc},
884         {"register_read", (PyCFunction) cpy_register_read, METH_VARARGS | METH_KEYWORDS, reg_read_doc},
885         {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, reg_write_doc},
886         {"register_notification", (PyCFunction) cpy_register_notification, METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
887         {"register_flush", (PyCFunction) cpy_register_flush, METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
888         {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
889         {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
890         {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
891         {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
892         {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
893         {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
894         {"unregister_notification", cpy_unregister_notification, METH_O, unregister_doc},
895         {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
896         {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
897         {0, 0, 0, 0}
898 };
900 static int cpy_shutdown(void) {
901         cpy_callback_t *c;
902         PyObject *ret;
904         /* This can happen if the module was loaded but not configured. */
905         if (state != NULL)
906                 PyEval_RestoreThread(state);
908         for (c = cpy_shutdown_callbacks; c; c = c->next) {
909                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
910                 if (ret == NULL)
911                         cpy_log_exception("shutdown callback");
912                 else
913                         Py_DECREF(ret);
914         }
915         PyErr_Print();
916         Py_Finalize();
917         return 0;
920 static void cpy_int_handler(int sig) {
921         return;
924 static void *cpy_interactive(void *data) {
925         sigset_t sigset;
926         struct sigaction sig_int_action, old;
928         /* Signal handler in a plugin? Bad stuff, but the best way to
929          * handle it I guess. In an interactive session people will
930          * press Ctrl+C at some time, which will generate a SIGINT.
931          * This will cause collectd to shutdown, thus killing the
932          * interactive interpreter, and leaving the terminal in a
933          * mess. Chances are, this isn't what the user wanted to do.
934          *
935          * So this is the plan:
936          * 1. Block SIGINT in the main thread.
937          * 2. Install our own signal handler that does nothing.
938          * 3. Unblock SIGINT in the interactive thread.
939          *
940          * This will make sure that SIGINT won't kill collectd but
941          * still interrupt syscalls like sleep and pause.
942          * It does not raise a KeyboardInterrupt exception because so
943          * far nobody managed to figure out how to do that. */
944         memset (&sig_int_action, '\0', sizeof (sig_int_action));
945         sig_int_action.sa_handler = cpy_int_handler;
946         sigaction (SIGINT, &sig_int_action, &old);
948         sigemptyset(&sigset);
949         sigaddset(&sigset, SIGINT);
950         pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
951         PyEval_AcquireThread(state);
952         if (PyImport_ImportModule("readline") == NULL) {
953                 /* This interactive session will suck. */
954                 cpy_log_exception("interactive session init");
955         }
956         PyRun_InteractiveLoop(stdin, "<stdin>");
957         PyErr_Print();
958         PyEval_ReleaseThread(state);
959         NOTICE("python: Interactive interpreter exited, stopping collectd ...");
960         /* Restore the original collectd SIGINT handler and raise SIGINT.
961          * The main thread still has SIGINT blocked and there's nothing we
962          * can do about that so this thread will handle it. But that's not
963          * important, except that it won't interrupt the main loop and so
964          * it might take a few seconds before collectd really shuts down. */
965         sigaction (SIGINT, &old, NULL);
966         raise(SIGINT);
967         pause();
968         return NULL;
971 static int cpy_init(void) {
972         cpy_callback_t *c;
973         PyObject *ret;
974         static pthread_t thread;
975         sigset_t sigset;
977         if (!Py_IsInitialized()) {
978                 WARNING("python: Plugin loaded but not configured.");
979                 plugin_unregister_shutdown("python");
980                 return 0;
981         }
982         PyEval_InitThreads();
983         /* Now it's finally OK to use python threads. */
984         for (c = cpy_init_callbacks; c; c = c->next) {
985                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
986                 if (ret == NULL)
987                         cpy_log_exception("init callback");
988                 else
989                         Py_DECREF(ret);
990         }
991         sigemptyset(&sigset);
992         sigaddset(&sigset, SIGINT);
993         pthread_sigmask(SIG_BLOCK, &sigset, NULL);
994         state = PyEval_SaveThread();
995         if (do_interactive) {
996                 if (plugin_thread_create(&thread, NULL, cpy_interactive, NULL)) {
997                         ERROR("python: Error creating thread for interactive interpreter.");
998                 }
999         }
1001         return 0;
1004 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
1005         int i;
1006         PyObject *item, *values, *children, *tmp;
1008         if (parent == NULL)
1009                 parent = Py_None;
1011         values = PyTuple_New(ci->values_num); /* New reference. */
1012         for (i = 0; i < ci->values_num; ++i) {
1013                 if (ci->values[i].type == OCONFIG_TYPE_STRING) {
1014                         PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
1015                 } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
1016                         PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
1017                 } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
1018                         PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
1019                 }
1020         }
1022         tmp = cpy_string_to_unicode_or_bytes(ci->key);
1023         item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
1024         if (item == NULL)
1025                 return NULL;
1026         children = PyTuple_New(ci->children_num); /* New reference. */
1027         for (i = 0; i < ci->children_num; ++i) {
1028                 PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
1029         }
1030         tmp = ((Config *) item)->children;
1031         ((Config *) item)->children = children;
1032         Py_XDECREF(tmp);
1033         return item;
1036 #ifdef IS_PY3K
1037 static struct PyModuleDef collectdmodule = {
1038         PyModuleDef_HEAD_INIT,
1039         "collectd",   /* name of module */
1040         "The python interface to collectd", /* module documentation, may be NULL */
1041         -1,
1042         cpy_methods
1043 };
1045 PyMODINIT_FUNC PyInit_collectd(void) {
1046         return PyModule_Create(&collectdmodule);
1048 #endif
1050 static int cpy_init_python(void) {
1051         PyObject *sys;
1052         PyObject *module;
1054 #ifdef IS_PY3K
1055         wchar_t *argv = L"";
1056         /* Add a builtin module, before Py_Initialize */
1057         PyImport_AppendInittab("collectd", PyInit_collectd);
1058 #else
1059         char *argv = "";
1060 #endif
1062         Py_Initialize();
1064         PyType_Ready(&ConfigType);
1065         PyType_Ready(&PluginDataType);
1066         ValuesType.tp_base = &PluginDataType;
1067         PyType_Ready(&ValuesType);
1068         NotificationType.tp_base = &PluginDataType;
1069         PyType_Ready(&NotificationType);
1070         SignedType.tp_base = &PyLong_Type;
1071         PyType_Ready(&SignedType);
1072         UnsignedType.tp_base = &PyLong_Type;
1073         PyType_Ready(&UnsignedType);
1074         sys = PyImport_ImportModule("sys"); /* New reference. */
1075         if (sys == NULL) {
1076                 cpy_log_exception("python initialization");
1077                 return 1;
1078         }
1079         sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1080         Py_DECREF(sys);
1081         if (sys_path == NULL) {
1082                 cpy_log_exception("python initialization");
1083                 return 1;
1084         }
1085         PySys_SetArgv(1, &argv);
1086         PyList_SetSlice(sys_path, 0, 1, NULL);
1088 #ifdef IS_PY3K
1089         module = PyImport_ImportModule("collectd");
1090 #else
1091         module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1092 #endif
1093         PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
1094         PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
1095         PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
1096         PyModule_AddObject(module, "Signed", (void *) &SignedType); /* Steals a reference. */
1097         PyModule_AddObject(module, "Unsigned", (void *) &UnsignedType); /* Steals a reference. */
1098         PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1099         PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1100         PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1101         PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1102         PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1103         PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1104         PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1105         PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1106         PyModule_AddStringConstant(module, "DS_TYPE_COUNTER", DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1107         PyModule_AddStringConstant(module, "DS_TYPE_GAUGE", DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1108         PyModule_AddStringConstant(module, "DS_TYPE_DERIVE", DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1109         PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE", DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1110         return 0;
1113 static int cpy_config(oconfig_item_t *ci) {
1114         int i;
1115         PyObject *tb;
1117         /* Ok in theory we shouldn't do initialization at this point
1118          * but we have to. In order to give python scripts a chance
1119          * to register a config callback we need to be able to execute
1120          * python code during the config callback so we have to start
1121          * the interpreter here. */
1122         /* Do *not* use the python "thread" module at this point! */
1124         if (!Py_IsInitialized() && cpy_init_python()) return 1;
1126         for (i = 0; i < ci->children_num; ++i) {
1127                 oconfig_item_t *item = ci->children + i;
1129                 if (strcasecmp(item->key, "Interactive") == 0) {
1130                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
1131                                 continue;
1132                         do_interactive = item->values[0].value.boolean;
1133                 } else if (strcasecmp(item->key, "Encoding") == 0) {
1134                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
1135                                 continue;
1136 #ifdef IS_PY3K
1137                         NOTICE("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings. Ignoring this.");
1138 #else
1139                         /* Why is this even necessary? And undocumented? */
1140                         if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
1141                                 cpy_log_exception("setting default encoding");
1142 #endif
1143                 } else if (strcasecmp(item->key, "LogTraces") == 0) {
1144                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
1145                                 continue;
1146                         if (!item->values[0].value.boolean) {
1147                                 Py_XDECREF(cpy_format_exception);
1148                                 cpy_format_exception = NULL;
1149                                 continue;
1150                         }
1151                         if (cpy_format_exception)
1152                                 continue;
1153                         tb = PyImport_ImportModule("traceback"); /* New reference. */
1154                         if (tb == NULL) {
1155                                 cpy_log_exception("python initialization");
1156                                 continue;
1157                         }
1158                         cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1159                         Py_DECREF(tb);
1160                         if (cpy_format_exception == NULL)
1161                                 cpy_log_exception("python initialization");
1162                 } else if (strcasecmp(item->key, "ModulePath") == 0) {
1163                         char *dir = NULL;
1164                         PyObject *dir_object;
1166                         if (cf_util_get_string(item, &dir) != 0)
1167                                 continue;
1168                         dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1169                         if (dir_object == NULL) {
1170                                 ERROR("python plugin: Unable to convert \"%s\" to "
1171                                       "a python object.", dir);
1172                                 free(dir);
1173                                 cpy_log_exception("python initialization");
1174                                 continue;
1175                         }
1176                         if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1177                                 ERROR("python plugin: Unable to prepend \"%s\" to "
1178                                       "python module path.", dir);
1179                                 cpy_log_exception("python initialization");
1180                         }
1181                         Py_DECREF(dir_object);
1182                         free(dir);
1183                 } else if (strcasecmp(item->key, "Import") == 0) {
1184                         char *module_name = NULL;
1185                         PyObject *module;
1187                         if (cf_util_get_string(item, &module_name) != 0)
1188                                 continue;
1189                         module = PyImport_ImportModule(module_name); /* New reference. */
1190                         if (module == NULL) {
1191                                 ERROR("python plugin: Error importing module \"%s\".", module_name);
1192                                 cpy_log_exception("importing module");
1193                         }
1194                         free(module_name);
1195                         Py_XDECREF(module);
1196                 } else if (strcasecmp(item->key, "Module") == 0) {
1197                         char *name = NULL;
1198                         cpy_callback_t *c;
1199                         PyObject *ret;
1201                         if (cf_util_get_string(item, &name) != 0)
1202                                 continue;
1203                         for (c = cpy_config_callbacks; c; c = c->next) {
1204                                 if (strcasecmp(c->name + 7, name) == 0)
1205                                         break;
1206                         }
1207                         if (c == NULL) {
1208                                 WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1209                                         "but the plugin isn't loaded or didn't register "
1210                                         "a configuration callback.", name);
1211                                 free(name);
1212                                 continue;
1213                         }
1214                         free(name);
1215                         if (c->data == NULL)
1216                                 ret = PyObject_CallFunction(c->callback, "N",
1217                                         cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1218                         else
1219                                 ret = PyObject_CallFunction(c->callback, "NO",
1220                                         cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
1221                         if (ret == NULL)
1222                                 cpy_log_exception("loading module");
1223                         else
1224                                 Py_DECREF(ret);
1225                 } else {
1226                         WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
1227                 }
1228         }
1229         return 0;
1232 void module_register(void) {
1233         plugin_register_complex_config("python", cpy_config);
1234         plugin_register_init("python", cpy_init);
1235         plugin_register_shutdown("python", cpy_shutdown);