Merge branch 'collectd-5.5'
[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  **/
26
27 #include <Python.h>
28 #include <structmember.h>
29
30 #include <signal.h>
31
32 #include "collectd.h"
33
34 #include "common.h"
35
36 #include "cpython.h"
37
38 typedef struct cpy_callback_s {
39         char *name;
40         PyObject *callback;
41         PyObject *data;
42         struct cpy_callback_s *next;
43 } cpy_callback_t;
44
45 static char log_doc[] = "This function sends a string to all logging plugins.";
46
47 static char get_ds_doc[] = "get_dataset(name) -> definition\n"
48                 "\n"
49                 "Returns the definition of a dataset specified by name.\n"
50                 "\n"
51                 "'name' is a string specifying the dataset to query.\n"
52                 "'definition' is a list of 4-tuples. Every tuple represents a \n"
53                 "    data source within the data set and its 4 values are the \n"
54                 "    name, type, min and max value.\n"
55                 "    'name' is a string.\n"
56                 "    'type' is a string that is equal to either DS_TYPE_COUNTER,\n"
57                 "        DS_TYPE_GAUGE, DS_TYPE_DERIVE or DS_TYPE_ABSOLUTE.\n"
58                 "    'min' and 'max' are either a float or None.";
59
60 static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
61                 "\n"
62                 "Flushes the cache of another plugin.";
63
64 static char unregister_doc[] = "Unregisters a callback. This function needs exactly one parameter either\n"
65                 "the function to unregister or the callback identifier to unregister.";
66
67 static char reg_log_doc[] = "register_log(callback[, data][, name]) -> identifier\n"
68                 "\n"
69                 "Register a callback function for log messages.\n"
70                 "\n"
71                 "'callback' is a callable object that will be called every time something\n"
72                 "    is logged.\n"
73                 "'data' is an optional object that will be passed back to the callback\n"
74                 "    function every time it is called.\n"
75                 "'name' is an optional identifier for this callback. The default name\n"
76                 "    is 'python.<module>'.\n"
77                 "    Every callback needs a unique identifier, so if you want to\n"
78                 "    register this callback multiple time from the same module you need\n"
79                 "    to specify a name here.\n"
80                 "'identifier' is the full identifier assigned to this callback.\n"
81                 "\n"
82                 "The callback function will be called with two or three parameters:\n"
83                 "severity: An integer that should be compared to the LOG_ constants.\n"
84                 "message: The text to be logged.\n"
85                 "data: The optional data parameter passed to the register function.\n"
86                 "    If the parameter was omitted it will be omitted here, too.";
87
88 static char reg_init_doc[] = "register_init(callback[, data][, name]) -> identifier\n"
89                 "\n"
90                 "Register a callback function that will be executed once after the config.\n"
91                 "file has been read, all plugins heve been loaded and the collectd has\n"
92                 "forked into the background.\n"
93                 "\n"
94                 "'callback' is a callable object that will be executed.\n"
95                 "'data' is an optional object that will be passed back to the callback\n"
96                 "    function when it is called.\n"
97                 "'name' is an optional identifier for this callback. The default name\n"
98                 "    is 'python.<module>'.\n"
99                 "    Every callback needs a unique identifier, so if you want to\n"
100                 "    register this callback multiple time from the same module you need\n"
101                 "    to specify a name here.\n"
102                 "'identifier' is the full identifier assigned to this callback.\n"
103                 "\n"
104                 "The callback function will be called without parameters, except for\n"
105                 "data if it was supplied.";
106
107 static char reg_config_doc[] = "register_config(callback[, data][, name]) -> identifier\n"
108                 "\n"
109                 "Register a callback function for config file entries.\n"
110                 "'callback' is a callable object that will be called for every config block.\n"
111                 "'data' is an optional object that will be passed back to the callback\n"
112                 "    function every time it is called.\n"
113                 "'name' is an optional identifier for this callback. The default name\n"
114                 "    is 'python.<module>'.\n"
115                 "    Every callback needs a unique identifier, so if you want to\n"
116                 "    register this callback multiple time from the same module you need\n"
117                 "    to specify a name here.\n"
118                 "'identifier' is the full identifier assigned to this callback.\n"
119                 "\n"
120                 "The callback function will be called with one or two parameters:\n"
121                 "config: A Config object.\n"
122                 "data: The optional data parameter passed to the register function.\n"
123                 "    If the parameter was omitted it will be omitted here, too.";
124
125 static char reg_read_doc[] = "register_read(callback[, interval][, data][, name]) -> identifier\n"
126                 "\n"
127                 "Register a callback function for reading data. It will just be called\n"
128                 "in a fixed interval to signal that it's time to dispatch new values.\n"
129                 "'callback' is a callable object that will be called every time something\n"
130                 "    is logged.\n"
131                 "'interval' is the number of seconds between between calls to the callback\n"
132                 "    function. Full float precision is supported here.\n"
133                 "'data' is an optional object that will be passed back to the callback\n"
134                 "    function every time it is called.\n"
135                 "'name' is an optional identifier for this callback. The default name\n"
136                 "    is 'python.<module>'.\n"
137                 "    Every callback needs a unique identifier, so if you want to\n"
138                 "    register this callback multiple time from the same module you need\n"
139                 "    to specify a name here.\n"
140                 "'identifier' is the full identifier assigned to this callback.\n"
141                 "\n"
142                 "The callback function will be called without parameters, except for\n"
143                 "data if it was supplied.";
144
145 static char reg_write_doc[] = "register_write(callback[, data][, name]) -> identifier\n"
146                 "\n"
147                 "Register a callback function to receive values dispatched by other plugins.\n"
148                 "'callback' is a callable object that will be called every time a value\n"
149                 "    is dispatched.\n"
150                 "'data' is an optional object that will be passed back to the callback\n"
151                 "    function every time it is called.\n"
152                 "'name' is an optional identifier for this callback. The default name\n"
153                 "    is 'python.<module>'.\n"
154                 "    Every callback needs a unique identifier, so if you want to\n"
155                 "    register this callback multiple time from the same module you need\n"
156                 "    to specify a name here.\n"
157                 "'identifier' is the full identifier assigned to this callback.\n"
158                 "\n"
159                 "The callback function will be called with one or two parameters:\n"
160                 "values: A Values object which is a copy of the dispatched values.\n"
161                 "data: The optional data parameter passed to the register function.\n"
162                 "    If the parameter was omitted it will be omitted here, too.";
163
164 static char reg_notification_doc[] = "register_notification(callback[, data][, name]) -> identifier\n"
165                 "\n"
166                 "Register a callback function for notifications.\n"
167                 "'callback' is a callable object that will be called every time a notification\n"
168                 "    is dispatched.\n"
169                 "'data' is an optional object that will be passed back to the callback\n"
170                 "    function every time it is called.\n"
171                 "'name' is an optional identifier for this callback. The default name\n"
172                 "    is 'python.<module>'.\n"
173                 "    Every callback needs a unique identifier, so if you want to\n"
174                 "    register this callback multiple time from the same module you need\n"
175                 "    to specify a name here.\n"
176                 "'identifier' is the full identifier assigned to this callback.\n"
177                 "\n"
178                 "The callback function will be called with one or two parameters:\n"
179                 "notification: A copy of the notification that was dispatched.\n"
180                 "data: The optional data parameter passed to the register function.\n"
181                 "    If the parameter was omitted it will be omitted here, too.";
182
183 static char reg_flush_doc[] = "register_flush(callback[, data][, name]) -> identifier\n"
184                 "\n"
185                 "Register a callback function for flush messages.\n"
186                 "'callback' is a callable object that will be called every time a plugin\n"
187                 "    requests a flush for either this or all plugins.\n"
188                 "'data' is an optional object that will be passed back to the callback\n"
189                 "    function every time it is called.\n"
190                 "'name' is an optional identifier for this callback. The default name\n"
191                 "    is 'python.<module>'.\n"
192                 "    Every callback needs a unique identifier, so if you want to\n"
193                 "    register this callback multiple time from the same module you need\n"
194                 "    to specify a name here.\n"
195                 "'identifier' is the full identifier assigned to this callback.\n"
196                 "\n"
197                 "The callback function will be called with two or three parameters:\n"
198                 "timeout: Indicates that only data older than 'timeout' seconds is to\n"
199                 "    be flushed.\n"
200                 "id: Specifies which values are to be flushed.\n"
201                 "data: The optional data parameter passed to the register function.\n"
202                 "    If the parameter was omitted it will be omitted here, too.";
203
204 static char reg_shutdown_doc[] = "register_shutdown(callback[, data][, name]) -> identifier\n"
205                 "\n"
206                 "Register a callback function for collectd shutdown.\n"
207                 "'callback' is a callable object that will be called once collectd is\n"
208                 "    shutting down.\n"
209                 "'data' is an optional object that will be passed back to the callback\n"
210                 "    function if it is called.\n"
211                 "'name' is an optional identifier for this callback. The default name\n"
212                 "    is 'python.<module>'.\n"
213                 "    Every callback needs a unique identifier, so if you want to\n"
214                 "    register this callback multiple time from the same module you need\n"
215                 "    to specify a name here.\n"
216                 "'identifier' is the full identifier assigned to this callback.\n"
217                 "\n"
218                 "The callback function will be called with no parameters except for\n"
219                 "    data if it was supplied.";
220
221
222 static pthread_t main_thread;
223 static PyOS_sighandler_t python_sigint_handler;
224 static _Bool do_interactive = 0;
225 static int do_interactive = 0;
226
227 /* This is our global thread state. Python saves some stuff in thread-local
228  * storage. So if we allow the interpreter to run in the background
229  * (the scriptwriters might have created some threads from python), we have
230  * to save the state so we can resume it later after shutdown. */
231
232 static PyThreadState *state;
233
234 static PyObject *sys_path, *cpy_format_exception;
235
236 static cpy_callback_t *cpy_config_callbacks;
237 static cpy_callback_t *cpy_init_callbacks;
238 static cpy_callback_t *cpy_shutdown_callbacks;
239
240 static void cpy_destroy_user_data(void *data) {
241         cpy_callback_t *c = data;
242         free(c->name);
243         Py_DECREF(c->callback);
244         Py_XDECREF(c->data);
245         free(c);
246 }
247
248 /* You must hold the GIL to call this function!
249  * But if you managed to extract the callback parameter then you probably already do. */
250
251 static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) {
252         const char *module = NULL;
253         PyObject *mod = NULL;
254
255         if (name != NULL) {
256                 snprintf(buf, size, "python.%s", name);
257                 return;
258         }
259
260         mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
261         if (mod != NULL)
262                 module = cpy_unicode_or_bytes_to_string(&mod);
263
264         if (module != NULL) {
265                 snprintf(buf, size, "python.%s", module);
266                 Py_XDECREF(mod);
267                 PyErr_Clear();
268                 return;
269         }
270         Py_XDECREF(mod);
271
272         snprintf(buf, size, "python.%p", callback);
273         PyErr_Clear();
274 }
275
276 void cpy_log_exception(const char *context) {
277         int l = 0;
278         const char *typename = NULL, *message = NULL;
279         PyObject *type, *value, *traceback, *tn, *m, *list;
280
281         PyErr_Fetch(&type, &value, &traceback);
282         PyErr_NormalizeException(&type, &value, &traceback);
283         if (type == NULL) return;
284         tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
285         m = PyObject_Str(value); /* New reference. */
286         if (tn != NULL)
287                 typename = cpy_unicode_or_bytes_to_string(&tn);
288         if (m != NULL)
289                 message = cpy_unicode_or_bytes_to_string(&m);
290         if (typename == NULL)
291                 typename = "NamelessException";
292         if (message == NULL)
293                 message = "N/A";
294         Py_BEGIN_ALLOW_THREADS
295         ERROR("Unhandled python exception in %s: %s: %s", context, typename, message);
296         Py_END_ALLOW_THREADS
297         Py_XDECREF(tn);
298         Py_XDECREF(m);
299         if (!cpy_format_exception || !traceback) {
300                 PyErr_Clear();
301                 Py_DECREF(type);
302                 Py_XDECREF(value);
303                 Py_XDECREF(traceback);
304                 return;
305         }
306         list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. Steals references from "type", "value" and "traceback". */
307         if (list)
308                 l = PyObject_Length(list);
309
310         for (int i = 0; i < l; ++i) {
311                 PyObject *line;
312                 char const *msg;
313                 char *cpy;
314
315                 line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
316                 Py_INCREF(line);
317
318                 msg = cpy_unicode_or_bytes_to_string(&line);
319                 Py_DECREF(line);
320                 if (msg == NULL)
321                         continue;
322
323                 cpy = strdup(msg);
324                 if (cpy == NULL)
325                         continue;
326
327                 if (cpy[strlen(cpy) - 1] == '\n')
328                         cpy[strlen(cpy) - 1] = 0;
329
330                 Py_BEGIN_ALLOW_THREADS
331                 ERROR("%s", cpy);
332                 Py_END_ALLOW_THREADS
333
334                 free(cpy);
335         }
336
337         Py_XDECREF(list);
338         PyErr_Clear();
339 }
340
341 static int cpy_read_callback(user_data_t *data) {
342         cpy_callback_t *c = data->data;
343         PyObject *ret;
344
345         CPY_LOCK_THREADS
346                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
347                 if (ret == NULL) {
348                         cpy_log_exception("read callback");
349                 } else {
350                         Py_DECREF(ret);
351                 }
352         CPY_RELEASE_THREADS
353         if (ret == NULL)
354                 return 1;
355         return 0;
356 }
357
358 static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
359         cpy_callback_t *c = data->data;
360         PyObject *ret, *list, *temp, *dict = NULL;
361         Values *v;
362
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 (size_t 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;
396
397                         num = meta_data_toc(meta, &table);
398                         for (size_t 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;
405
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;
465 }
466
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;
471
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;
492 }
493
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;
497
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". */
504
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
516 }
517
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;
521
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. */
528
529         if (ret == NULL) {
530                 cpy_log_exception("flush callback");
531         } else {
532                 Py_DECREF(ret);
533         }
534         CPY_RELEASE_THREADS
535 }
536
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};
543
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);
551
552         Py_INCREF(callback);
553         Py_XINCREF(data);
554
555         c = calloc(1, sizeof(*c));
556         if (c == NULL)
557                 return NULL;
558
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);
567 }
568
569 static PyObject *float_or_none(float number) {
570         if (isnan(number)) {
571                 Py_RETURN_NONE;
572         }
573         return PyFloat_FromDouble(number);
574 }
575
576 static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
577         char *name;
578         const data_set_t *ds;
579         PyObject *list, *tuple;
580
581         if (PyArg_ParseTuple(args, "et", NULL, &name) == 0) return NULL;
582         ds = plugin_get_ds(name);
583         PyMem_Free(name);
584         if (ds == NULL) {
585                 PyErr_Format(PyExc_TypeError, "Dataset %s not found", name);
586                 return NULL;
587         }
588         list = PyList_New(ds->ds_num); /* New reference. */
589         for (size_t i = 0; i < ds->ds_num; ++i) {
590                 tuple = PyTuple_New(4);
591                 PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
592                 PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
593                 PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min));
594                 PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max));
595                 PyList_SET_ITEM(list, i, tuple);
596         }
597         return list;
598 }
599
600 static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
601         int timeout = -1;
602         char *plugin = NULL, *identifier = NULL;
603         static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
604
605         if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
606         Py_BEGIN_ALLOW_THREADS
607         plugin_flush(plugin, timeout, identifier);
608         Py_END_ALLOW_THREADS
609         PyMem_Free(plugin);
610         PyMem_Free(identifier);
611         Py_RETURN_NONE;
612 }
613
614 static PyObject *cpy_register_config(PyObject *self, PyObject *args, PyObject *kwds) {
615         return cpy_register_generic(&cpy_config_callbacks, args, kwds);
616 }
617
618 static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwds) {
619         return cpy_register_generic(&cpy_init_callbacks, args, kwds);
620 }
621
622 typedef int reg_function_t(const char *name, void *callback, void *data);
623
624 static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) {
625         char buf[512];
626         reg_function_t *register_function = (reg_function_t *) reg;
627         cpy_callback_t *c = NULL;
628         user_data_t user_data = { 0 };
629         char *name = NULL;
630         PyObject *callback = NULL, *data = NULL;
631         static char *kwlist[] = {"callback", "data", "name", NULL};
632
633         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
634         if (PyCallable_Check(callback) == 0) {
635                 PyMem_Free(name);
636                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
637                 return NULL;
638         }
639         cpy_build_name(buf, sizeof(buf), callback, name);
640         PyMem_Free(name);
641
642         Py_INCREF(callback);
643         Py_XINCREF(data);
644
645         c = calloc(1, sizeof(*c));
646         if (c == NULL)
647                 return NULL;
648
649         c->name = strdup(buf);
650         c->callback = callback;
651         c->data = data;
652         c->next = NULL;
653
654         user_data.free_func = cpy_destroy_user_data;
655         user_data.data = c;
656
657         register_function(buf, handler, &user_data);
658         return cpy_string_to_unicode_or_bytes(buf);
659 }
660
661 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
662         char buf[512];
663         cpy_callback_t *c = NULL;
664         user_data_t user_data = { 0 };
665         double interval = 0;
666         char *name = NULL;
667         PyObject *callback = NULL, *data = NULL;
668         static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
669
670         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
671         if (PyCallable_Check(callback) == 0) {
672                 PyMem_Free(name);
673                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
674                 return NULL;
675         }
676         cpy_build_name(buf, sizeof(buf), callback, name);
677         PyMem_Free(name);
678
679         Py_INCREF(callback);
680         Py_XINCREF(data);
681
682         c = calloc(1, sizeof(*c));
683         if (c == NULL)
684                 return NULL;
685
686         c->name = strdup(buf);
687         c->callback = callback;
688         c->data = data;
689         c->next = NULL;
690
691         user_data.free_func = cpy_destroy_user_data;
692         user_data.data = c;
693
694         plugin_register_complex_read(/* group = */ "python", buf,
695                         cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
696         return cpy_string_to_unicode_or_bytes(buf);
697 }
698
699 static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
700         return cpy_register_generic_userdata((void *) plugin_register_log,
701                         (void *) cpy_log_callback, args, kwds);
702 }
703
704 static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) {
705         return cpy_register_generic_userdata((void *) plugin_register_write,
706                         (void *) cpy_write_callback, args, kwds);
707 }
708
709 static PyObject *cpy_register_notification(PyObject *self, PyObject *args, PyObject *kwds) {
710         return cpy_register_generic_userdata((void *) plugin_register_notification,
711                         (void *) cpy_notification_callback, args, kwds);
712 }
713
714 static PyObject *cpy_register_flush(PyObject *self, PyObject *args, PyObject *kwds) {
715         return cpy_register_generic_userdata((void *) plugin_register_flush,
716                         (void *) cpy_flush_callback, args, kwds);
717 }
718
719 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) {
720         return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
721 }
722
723 static PyObject *cpy_error(PyObject *self, PyObject *args) {
724         char *text;
725         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
726         Py_BEGIN_ALLOW_THREADS
727         plugin_log(LOG_ERR, "%s", text);
728         Py_END_ALLOW_THREADS
729         PyMem_Free(text);
730         Py_RETURN_NONE;
731 }
732
733 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
734         char *text;
735         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
736         Py_BEGIN_ALLOW_THREADS
737         plugin_log(LOG_WARNING, "%s", text);
738         Py_END_ALLOW_THREADS
739         PyMem_Free(text);
740         Py_RETURN_NONE;
741 }
742
743 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
744         char *text;
745         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
746         Py_BEGIN_ALLOW_THREADS
747         plugin_log(LOG_NOTICE, "%s", text);
748         Py_END_ALLOW_THREADS
749         PyMem_Free(text);
750         Py_RETURN_NONE;
751 }
752
753 static PyObject *cpy_info(PyObject *self, PyObject *args) {
754         char *text;
755         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
756         Py_BEGIN_ALLOW_THREADS
757         plugin_log(LOG_INFO, "%s", text);
758         Py_END_ALLOW_THREADS
759         PyMem_Free(text);
760         Py_RETURN_NONE;
761 }
762
763 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
764 #ifdef COLLECT_DEBUG
765         char *text;
766         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
767         Py_BEGIN_ALLOW_THREADS
768         plugin_log(LOG_DEBUG, "%s", text);
769         Py_END_ALLOW_THREADS
770         PyMem_Free(text);
771 #endif
772         Py_RETURN_NONE;
773 }
774
775 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *arg, const char *desc) {
776         char buf[512];
777         const char *name;
778         cpy_callback_t *prev = NULL, *tmp;
779
780         Py_INCREF(arg);
781         name = cpy_unicode_or_bytes_to_string(&arg);
782         if (name == NULL) {
783                 PyErr_Clear();
784                 if (!PyCallable_Check(arg)) {
785                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
786                         Py_DECREF(arg);
787                         return NULL;
788                 }
789                 cpy_build_name(buf, sizeof(buf), arg, NULL);
790                 name = buf;
791         }
792         for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
793                 if (strcmp(name, tmp->name) == 0)
794                         break;
795
796         Py_DECREF(arg);
797         if (tmp == NULL) {
798                 PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
799                 return NULL;
800         }
801         /* Yes, this is actually save. To call this function the caller has to
802          * hold the GIL. Well, save as long as there is only one GIL anyway ... */
803         if (prev == NULL)
804                 *list_head = tmp->next;
805         else
806                 prev->next = tmp->next;
807         cpy_destroy_user_data(tmp);
808         Py_RETURN_NONE;
809 }
810
811 typedef int cpy_unregister_function_t(const char *name);
812
813 static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
814         char buf[512];
815         const char *name;
816
817         Py_INCREF(arg);
818         name = cpy_unicode_or_bytes_to_string(&arg);
819         if (name == NULL) {
820                 PyErr_Clear();
821                 if (!PyCallable_Check(arg)) {
822                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
823                         Py_DECREF(arg);
824                         return NULL;
825                 }
826                 cpy_build_name(buf, sizeof(buf), arg, NULL);
827                 name = buf;
828         }
829         if (unreg(name) == 0) {
830                 Py_DECREF(arg);
831                 Py_RETURN_NONE;
832         }
833         PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
834         Py_DECREF(arg);
835         return NULL;
836 }
837
838 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
839         return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
840 }
841
842 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
843         return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
844 }
845
846 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
847         return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
848 }
849
850 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
851         return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
852 }
853
854 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
855         return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
856 }
857
858 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
859         return cpy_unregister_generic_userdata(plugin_unregister_notification, arg, "notification");
860 }
861
862 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
863         return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
864 }
865
866 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
867         return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
868 }
869
870 static PyMethodDef cpy_methods[] = {
871         {"debug", cpy_debug, METH_VARARGS, log_doc},
872         {"info", cpy_info, METH_VARARGS, log_doc},
873         {"notice", cpy_notice, METH_VARARGS, log_doc},
874         {"warning", cpy_warning, METH_VARARGS, log_doc},
875         {"error", cpy_error, METH_VARARGS, log_doc},
876         {"get_dataset", (PyCFunction) cpy_get_dataset, METH_VARARGS, get_ds_doc},
877         {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
878         {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
879         {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
880         {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, reg_config_doc},
881         {"register_read", (PyCFunction) cpy_register_read, METH_VARARGS | METH_KEYWORDS, reg_read_doc},
882         {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, reg_write_doc},
883         {"register_notification", (PyCFunction) cpy_register_notification, METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
884         {"register_flush", (PyCFunction) cpy_register_flush, METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
885         {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
886         {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
887         {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
888         {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
889         {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
890         {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
891         {"unregister_notification", cpy_unregister_notification, METH_O, unregister_doc},
892         {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
893         {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
894         {0, 0, 0, 0}
895 };
896
897 static int cpy_shutdown(void) {
898         PyObject *ret;
899
900         /* This can happen if the module was loaded but not configured. */
901         if (state != NULL)
902                 PyEval_RestoreThread(state);
903
904         for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
905                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
906                 if (ret == NULL)
907                         cpy_log_exception("shutdown callback");
908                 else
909                         Py_DECREF(ret);
910         }
911         PyErr_Print();
912         Py_Finalize();
913         return 0;
914 }
915
916 static void *cpy_interactive(void *data) {
917         PyOS_sighandler_t cur_sig;
918
919         /* Signal handler in a plugin? Bad stuff, but the best way to
920          * handle it I guess. In an interactive session people will
921          * press Ctrl+C at some time, which will generate a SIGINT.
922          * This will cause collectd to shutdown, thus killing the
923          * interactive interpreter, and leaving the terminal in a
924          * mess. Chances are, this isn't what the user wanted to do.
925          *
926          * So this is the plan:
927          * 1. Restore Python's own signal handler
928          * 2. Tell Python we just forked so it will accept this thread
929          *    as the main one. No version of Python will ever handle
930          *    interrupts anywhere but in the main thread.
931          * 3. After the interactive loop is done, restore collectd's
932          *    SIGINT handler.
933          * 4. Raise SIGINT for a clean shutdown. The signal is sent to
934          *    the main thread to ensure it wakes up the main interval
935          *    sleep so that collectd shuts down immediately not in 10
936          *    seconds.
937          *
938          * This will make sure that SIGINT won't kill collectd but
939          * still interrupt syscalls like sleep and pause. */
940
941         PyEval_AcquireThread(state);
942         if (PyImport_ImportModule("readline") == NULL) {
943                 /* This interactive session will suck. */
944                 cpy_log_exception("interactive session init");
945         }
946         cur_sig = PyOS_setsig(SIGINT, python_sigint_handler);
947         /* We totally forked just now. Everyone saw that, right? */
948         PyOS_AfterFork();
949         PyRun_InteractiveLoop(stdin, "<stdin>");
950         PyOS_setsig(SIGINT, cur_sig);
951         PyErr_Print();
952         PyEval_ReleaseThread(state);
953         NOTICE("python: Interactive interpreter exited, stopping collectd ...");
954         pthread_kill(main_thread, SIGINT);
955         return NULL;
956 }
957
958 static int cpy_init(void) {
959         PyObject *ret;
960         static pthread_t thread;
961
962         if (!Py_IsInitialized()) {
963                 WARNING("python: Plugin loaded but not configured.");
964                 plugin_unregister_shutdown("python");
965                 return 0;
966         }
967         PyEval_InitThreads();
968         /* Now it's finally OK to use python threads. */
969         for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
970                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
971                 if (ret == NULL)
972                         cpy_log_exception("init callback");
973                 else
974                         Py_DECREF(ret);
975         }
976         state = PyEval_SaveThread();
977         main_thread = pthread_self();
978         if (do_interactive) {
979                 if (plugin_thread_create(&thread, NULL, cpy_interactive, NULL)) {
980                         ERROR("python: Error creating thread for interactive interpreter.");
981                 }
982         }
983
984         return 0;
985 }
986
987 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
988         PyObject *item, *values, *children, *tmp;
989
990         if (parent == NULL)
991                 parent = Py_None;
992
993         values = PyTuple_New(ci->values_num); /* New reference. */
994         for (int i = 0; i < ci->values_num; ++i) {
995                 if (ci->values[i].type == OCONFIG_TYPE_STRING) {
996                         PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
997                 } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
998                         PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
999                 } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
1000                         PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
1001                 }
1002         }
1003
1004         tmp = cpy_string_to_unicode_or_bytes(ci->key);
1005         item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
1006         if (item == NULL)
1007                 return NULL;
1008         children = PyTuple_New(ci->children_num); /* New reference. */
1009         for (int i = 0; i < ci->children_num; ++i) {
1010                 PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
1011         }
1012         tmp = ((Config *) item)->children;
1013         ((Config *) item)->children = children;
1014         Py_XDECREF(tmp);
1015         return item;
1016 }
1017
1018 #ifdef IS_PY3K
1019 static struct PyModuleDef collectdmodule = {
1020         PyModuleDef_HEAD_INIT,
1021         "collectd",   /* name of module */
1022         "The python interface to collectd", /* module documentation, may be NULL */
1023         -1,
1024         cpy_methods
1025 };
1026
1027 PyMODINIT_FUNC PyInit_collectd(void) {
1028         return PyModule_Create(&collectdmodule);
1029 }
1030 #endif
1031
1032 static int cpy_init_python(void) {
1033         PyOS_sighandler_t cur_sig;
1034         PyObject *sys;
1035         PyObject *module;
1036
1037 #ifdef IS_PY3K
1038         wchar_t *argv = L"";
1039         /* Add a builtin module, before Py_Initialize */
1040         PyImport_AppendInittab("collectd", PyInit_collectd);
1041 #else
1042         char *argv = "";
1043 #endif
1044
1045         /* Chances are the current signal handler is already SIG_DFL, but let's make sure. */
1046         cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
1047         Py_Initialize();
1048         python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
1049
1050         PyType_Ready(&ConfigType);
1051         PyType_Ready(&PluginDataType);
1052         ValuesType.tp_base = &PluginDataType;
1053         PyType_Ready(&ValuesType);
1054         NotificationType.tp_base = &PluginDataType;
1055         PyType_Ready(&NotificationType);
1056         SignedType.tp_base = &PyLong_Type;
1057         PyType_Ready(&SignedType);
1058         UnsignedType.tp_base = &PyLong_Type;
1059         PyType_Ready(&UnsignedType);
1060         sys = PyImport_ImportModule("sys"); /* New reference. */
1061         if (sys == NULL) {
1062                 cpy_log_exception("python initialization");
1063                 return 1;
1064         }
1065         sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1066         Py_DECREF(sys);
1067         if (sys_path == NULL) {
1068                 cpy_log_exception("python initialization");
1069                 return 1;
1070         }
1071         PySys_SetArgv(1, &argv);
1072         PyList_SetSlice(sys_path, 0, 1, NULL);
1073
1074 #ifdef IS_PY3K
1075         module = PyImport_ImportModule("collectd");
1076 #else
1077         module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1078 #endif
1079         PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
1080         PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
1081         PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
1082         PyModule_AddObject(module, "Signed", (void *) &SignedType); /* Steals a reference. */
1083         PyModule_AddObject(module, "Unsigned", (void *) &UnsignedType); /* Steals a reference. */
1084         PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1085         PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1086         PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1087         PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1088         PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1089         PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1090         PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1091         PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1092         PyModule_AddStringConstant(module, "DS_TYPE_COUNTER", DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1093         PyModule_AddStringConstant(module, "DS_TYPE_GAUGE", DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1094         PyModule_AddStringConstant(module, "DS_TYPE_DERIVE", DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1095         PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE", DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1096         return 0;
1097 }
1098
1099 static int cpy_config(oconfig_item_t *ci) {
1100         PyObject *tb;
1101         int status = 0;
1102
1103         /* Ok in theory we shouldn't do initialization at this point
1104          * but we have to. In order to give python scripts a chance
1105          * to register a config callback we need to be able to execute
1106          * python code during the config callback so we have to start
1107          * the interpreter here. */
1108         /* Do *not* use the python "thread" module at this point! */
1109
1110         if (!Py_IsInitialized() && cpy_init_python()) return 1;
1111
1112         for (int i = 0; i < ci->children_num; ++i) {
1113                 oconfig_item_t *item = ci->children + i;
1114
1115                 if (strcasecmp(item->key, "Interactive") == 0) {
1116                         if (cf_util_get_boolean(item, &do_interactive) != 0) {
1117                                 status = 1;
1118                                 continue;
1119                         }
1120                 } else if (strcasecmp(item->key, "Encoding") == 0) {
1121                         char *encoding = NULL;
1122                         if (cf_util_get_string(item, &encoding) != 0) {
1123                                 status = 1;
1124                                 continue;
1125                         }
1126 #ifdef IS_PY3K
1127                         ERROR("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings");
1128                         status = 1;
1129                         sfree(encoding);
1130                         continue;
1131 #else
1132                         /* Why is this even necessary? And undocumented? */
1133                         if (PyUnicode_SetDefaultEncoding(encoding)) {
1134                                 cpy_log_exception("setting default encoding");
1135                                 status = 1;
1136                         }
1137 #endif
1138                         sfree(encoding);
1139                 } else if (strcasecmp(item->key, "LogTraces") == 0) {
1140                         _Bool log_traces;
1141                         if (cf_util_get_boolean(item, &log_traces) != 0) {
1142                                 status = 1;
1143                                 continue;
1144                         }
1145                         if (!log_traces) {
1146                                 Py_XDECREF(cpy_format_exception);
1147                                 cpy_format_exception = NULL;
1148                                 continue;
1149                         }
1150                         if (cpy_format_exception)
1151                                 continue;
1152                         tb = PyImport_ImportModule("traceback"); /* New reference. */
1153                         if (tb == NULL) {
1154                                 cpy_log_exception("python initialization");
1155                                 status = 1;
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                                 status = 1;
1163                         }
1164                 } else if (strcasecmp(item->key, "ModulePath") == 0) {
1165                         char *dir = NULL;
1166                         PyObject *dir_object;
1167
1168                         if (cf_util_get_string(item, &dir) != 0) {
1169                                 status = 1;
1170                                 continue;
1171                         }
1172                         dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1173                         if (dir_object == NULL) {
1174                                 ERROR("python plugin: Unable to convert \"%s\" to "
1175                                       "a python object.", dir);
1176                                 free(dir);
1177                                 cpy_log_exception("python initialization");
1178                                 status = 1;
1179                                 continue;
1180                         }
1181                         if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1182                                 ERROR("python plugin: Unable to prepend \"%s\" to "
1183                                       "python module path.", dir);
1184                                 cpy_log_exception("python initialization");
1185                                 status = 1;
1186                         }
1187                         Py_DECREF(dir_object);
1188                         free(dir);
1189                 } else if (strcasecmp(item->key, "Import") == 0) {
1190                         char *module_name = NULL;
1191                         PyObject *module;
1192
1193                         if (cf_util_get_string(item, &module_name) != 0) {
1194                                 status = 1;
1195                                 continue;
1196                         }
1197                         module = PyImport_ImportModule(module_name); /* New reference. */
1198                         if (module == NULL) {
1199                                 ERROR("python plugin: Error importing module \"%s\".", module_name);
1200                                 cpy_log_exception("importing module");
1201                                 status = 1;
1202                         }
1203                         free(module_name);
1204                         Py_XDECREF(module);
1205                 } else if (strcasecmp(item->key, "Module") == 0) {
1206                         char *name = NULL;
1207                         cpy_callback_t *c;
1208                         PyObject *ret;
1209
1210                         if (cf_util_get_string(item, &name) != 0) {
1211                                 status = 1;
1212                                 continue;
1213                         }
1214                         for (c = cpy_config_callbacks; c; c = c->next) {
1215                                 if (strcasecmp(c->name + 7, name) == 0)
1216                                         break;
1217                         }
1218                         if (c == NULL) {
1219                                 WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1220                                         "but the plugin isn't loaded or didn't register "
1221                                         "a configuration callback.", name);
1222                                 free(name);
1223                                 continue;
1224                         }
1225                         free(name);
1226                         if (c->data == NULL)
1227                                 ret = PyObject_CallFunction(c->callback, "N",
1228                                         cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1229                         else
1230                                 ret = PyObject_CallFunction(c->callback, "NO",
1231                                         cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
1232                         if (ret == NULL) {
1233                                 cpy_log_exception("loading module");
1234                                 status = 1;
1235                         } else
1236                                 Py_DECREF(ret);
1237                 } else {
1238                         ERROR("python plugin: Unknown config key \"%s\".", item->key);
1239                         status = 1;
1240                 }
1241         }
1242         return (status);
1243 }
1244
1245 void module_register(void) {
1246         plugin_register_complex_config("python", cpy_config);
1247         plugin_register_init("python", cpy_init);
1248         plugin_register_shutdown("python", cpy_shutdown);
1249 }