Add missing kstat definitions
[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 #if HAVE_PTHREAD_H
32 # include <pthread.h>
33 #endif
34
35 #include "collectd.h"
36 #include "common.h"
37
38 #include "cpython.h"
39
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;
46
47 static char log_doc[] = "This function sends a string to all logging plugins.";
48
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.";
61
62 static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
63                 "\n"
64                 "Flushes the cache of another plugin.";
65
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.";
68
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.";
89
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.";
108
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.";
126
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.";
146
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.";
165
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.";
184
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.";
205
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.";
222
223
224 static int do_interactive = 0;
225
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. */
230
231 static PyThreadState *state;
232
233 static PyObject *sys_path, *cpy_format_exception;
234
235 static cpy_callback_t *cpy_config_callbacks;
236 static cpy_callback_t *cpy_init_callbacks;
237 static cpy_callback_t *cpy_shutdown_callbacks;
238
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);
245 }
246
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. */
249
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;
253         
254         if (name != NULL) {
255                 snprintf(buf, size, "python.%s", name);
256                 return;
257         }
258         
259         mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
260         if (mod != NULL)
261                 module = cpy_unicode_or_bytes_to_string(&mod);
262         
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);
270         
271         snprintf(buf, size, "python.%p", callback);
272         PyErr_Clear();
273 }
274
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;
279         
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. */
306         if (list)
307                 l = PyObject_Length(list);
308         for (i = 0; i < l; ++i) {
309                 char *s;
310                 PyObject *line;
311                 
312                 line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
313                 Py_INCREF(line);
314                 s = strdup(cpy_unicode_or_bytes_to_string(&line));
315                 Py_DECREF(line);
316                 if (s[strlen(s) - 1] == '\n')
317                         s[strlen(s) - 1] = 0;
318                 Py_BEGIN_ALLOW_THREADS
319                 ERROR("%s", s);
320                 Py_END_ALLOW_THREADS
321                 free(s);
322         }
323         Py_XDECREF(list);
324         PyErr_Clear();
325         Py_DECREF(type);
326         Py_XDECREF(value);
327         Py_XDECREF(traceback);
328 }
329
330 static int cpy_read_callback(user_data_t *data) {
331         cpy_callback_t *c = data->data;
332         PyObject *ret;
333
334         CPY_LOCK_THREADS
335                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
336                 if (ret == NULL) {
337                         cpy_log_exception("read callback");
338                 } else {
339                         Py_DECREF(ret);
340                 }
341         CPY_RELEASE_THREADS
342         if (ret == NULL)
343                 return 1;
344         return 0;
345 }
346
347 static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
348         size_t i;
349         cpy_callback_t *c = data->data;
350         PyObject *ret, *list, *temp, *dict = NULL;
351         Values *v;
352
353         CPY_LOCK_THREADS
354                 list = PyList_New(value_list->values_len); /* New reference. */
355                 if (list == NULL) {
356                         cpy_log_exception("write callback");
357                         CPY_RETURN_FROM_THREADS 0;
358                 }
359                 for (i = 0; i < value_list->values_len; ++i) {
360                         if (ds->ds[i].type == DS_TYPE_COUNTER) {
361                                 PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
362                         } else if (ds->ds[i].type == DS_TYPE_GAUGE) {
363                                 PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
364                         } else if (ds->ds[i].type == DS_TYPE_DERIVE) {
365                                 PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
366                         } else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
367                                 PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
368                         } else {
369                                 Py_BEGIN_ALLOW_THREADS
370                                 ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
371                                 Py_END_ALLOW_THREADS
372                                 Py_DECREF(list);
373                                 CPY_RETURN_FROM_THREADS 0;
374                         }
375                         if (PyErr_Occurred() != NULL) {
376                                 cpy_log_exception("value building for write callback");
377                                 Py_DECREF(list);
378                                 CPY_RETURN_FROM_THREADS 0;
379                         }
380                 }
381                 dict = PyDict_New();  /* New reference. */
382                 if (value_list->meta) {
383                         int i, num;
384                         char **table;
385                         meta_data_t *meta = value_list->meta;
386
387                         num = meta_data_toc(meta, &table);
388                         for (i = 0; i < num; ++i) {
389                                 int type;
390                                 char *string;
391                                 int64_t si;
392                                 uint64_t ui;
393                                 double d;
394                                 _Bool b;
395                                 
396                                 type = meta_data_type(meta, table[i]);
397                                 if (type == MD_TYPE_STRING) {
398                                         if (meta_data_get_string(meta, table[i], &string))
399                                                 continue;
400                                         temp = cpy_string_to_unicode_or_bytes(string);  /* New reference. */
401                                         free(string);
402                                         PyDict_SetItemString(dict, table[i], temp);
403                                         Py_XDECREF(temp);
404                                 } else if (type == MD_TYPE_SIGNED_INT) {
405                                         if (meta_data_get_signed_int(meta, table[i], &si))
406                                                 continue;
407                                         temp = PyObject_CallFunctionObjArgs((void *) &SignedType, PyLong_FromLongLong(si), (void *) 0);  /* New reference. */
408                                         PyDict_SetItemString(dict, table[i], temp);
409                                         Py_XDECREF(temp);
410                                 } else if (type == MD_TYPE_UNSIGNED_INT) {
411                                         if (meta_data_get_unsigned_int(meta, table[i], &ui))
412                                                 continue;
413                                         temp = PyObject_CallFunctionObjArgs((void *) &UnsignedType, PyLong_FromUnsignedLongLong(ui), (void *) 0);  /* New reference. */
414                                         PyDict_SetItemString(dict, table[i], temp);
415                                         Py_XDECREF(temp);
416                                 } else if (type == MD_TYPE_DOUBLE) {
417                                         if (meta_data_get_double(meta, table[i], &d))
418                                                 continue;
419                                         temp = PyFloat_FromDouble(d);  /* New reference. */
420                                         PyDict_SetItemString(dict, table[i], temp);
421                                         Py_XDECREF(temp);
422                                 } else if (type == MD_TYPE_BOOLEAN) {
423                                         if (meta_data_get_boolean(meta, table[i], &b))
424                                                 continue;
425                                         if (b)
426                                                 PyDict_SetItemString(dict, table[i], Py_True);
427                                         else
428                                                 PyDict_SetItemString(dict, table[i], Py_False);
429                                 }
430                                 free(table[i]);
431                         }
432                         free(table);
433                 }
434                 v = (Values *) Values_New(); /* New reference. */
435                 sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
436                 sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
437                 sstrncpy(v->data.type_instance, value_list->type_instance, sizeof(v->data.type_instance));
438                 sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
439                 sstrncpy(v->data.plugin_instance, value_list->plugin_instance, sizeof(v->data.plugin_instance));
440                 v->data.time = CDTIME_T_TO_DOUBLE(value_list->time);
441                 v->interval = CDTIME_T_TO_DOUBLE(value_list->interval);
442                 Py_CLEAR(v->values);
443                 v->values = list;
444                 Py_CLEAR(v->meta);
445                 v->meta = dict;  /* Steals a reference. */
446                 ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
447                 Py_XDECREF(v);
448                 if (ret == NULL) {
449                         cpy_log_exception("write callback");
450                 } else {
451                         Py_DECREF(ret);
452                 }
453         CPY_RELEASE_THREADS
454         return 0;
455 }
456
457 static int cpy_notification_callback(const notification_t *notification, user_data_t *data) {
458         cpy_callback_t *c = data->data;
459         PyObject *ret, *notify;
460         Notification *n;
461
462         CPY_LOCK_THREADS
463                 notify = Notification_New(); /* New reference. */
464                 n = (Notification *) notify;
465                 sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
466                 sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
467                 sstrncpy(n->data.type_instance, notification->type_instance, sizeof(n->data.type_instance));
468                 sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
469                 sstrncpy(n->data.plugin_instance, notification->plugin_instance, sizeof(n->data.plugin_instance));
470                 n->data.time = CDTIME_T_TO_DOUBLE(notification->time);
471                 sstrncpy(n->message, notification->message, sizeof(n->message));
472                 n->severity = notification->severity;
473                 ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
474                 Py_XDECREF(notify);
475                 if (ret == NULL) {
476                         cpy_log_exception("notification callback");
477                 } else {
478                         Py_DECREF(ret);
479                 }
480         CPY_RELEASE_THREADS
481         return 0;
482 }
483
484 static void cpy_log_callback(int severity, const char *message, user_data_t *data) {
485         cpy_callback_t * c = data->data;
486         PyObject *ret, *text;
487
488         CPY_LOCK_THREADS
489         text = cpy_string_to_unicode_or_bytes(message);  /* New reference. */
490         if (c->data == NULL)
491                 ret = PyObject_CallFunction(c->callback, "iN", severity, text); /* New reference. Steals a reference from "text". */
492         else
493                 ret = PyObject_CallFunction(c->callback, "iNO", severity, text, c->data); /* New reference. Steals a reference from "text". */
494
495         if (ret == NULL) {
496                 /* FIXME */
497                 /* Do we really want to trigger a log callback because a log callback failed?
498                  * Probably not. */
499                 PyErr_Print();
500                 /* In case someone wanted to be clever, replaced stderr and failed at that. */
501                 PyErr_Clear();
502         } else {
503                 Py_DECREF(ret);
504         }
505         CPY_RELEASE_THREADS
506 }
507
508 static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
509         cpy_callback_t * c = data->data;
510         PyObject *ret, *text;
511
512         CPY_LOCK_THREADS
513         text = cpy_string_to_unicode_or_bytes(id);
514         if (c->data == NULL)
515                 ret = PyObject_CallFunction(c->callback, "iN", timeout, text); /* New reference. */
516         else
517                 ret = PyObject_CallFunction(c->callback, "iNO", timeout, text, c->data); /* New reference. */
518
519         if (ret == NULL) {
520                 cpy_log_exception("flush callback");
521         } else {
522                 Py_DECREF(ret);
523         }
524         CPY_RELEASE_THREADS
525 }
526
527 static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
528         char buf[512];
529         cpy_callback_t *c;
530         char *name = NULL;
531         PyObject *callback = NULL, *data = NULL, *mod = NULL;
532         static char *kwlist[] = {"callback", "data", "name", NULL};
533         
534         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
535         if (PyCallable_Check(callback) == 0) {
536                 PyMem_Free(name);
537                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
538                 return NULL;
539         }
540         cpy_build_name(buf, sizeof(buf), callback, name);
541
542         Py_INCREF(callback);
543         Py_XINCREF(data);
544         c = malloc(sizeof(*c));
545         c->name = strdup(buf);
546         c->callback = callback;
547         c->data = data;
548         c->next = *list_head;
549         *list_head = c;
550         Py_XDECREF(mod);
551         PyMem_Free(name);
552         return cpy_string_to_unicode_or_bytes(buf);
553 }
554
555 static PyObject *float_or_none(float number) {
556         if (isnan(number)) {
557                 Py_RETURN_NONE;
558         }
559         return PyFloat_FromDouble(number);
560 }
561
562 static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
563         size_t i;
564         char *name;
565         const data_set_t *ds;
566         PyObject *list, *tuple;
567
568         if (PyArg_ParseTuple(args, "et", NULL, &name) == 0) return NULL;
569         ds = plugin_get_ds(name);
570         PyMem_Free(name);
571         if (ds == NULL) {
572                 PyErr_Format(PyExc_TypeError, "Dataset %s not found", name);
573                 return NULL;
574         }
575         list = PyList_New(ds->ds_num); /* New reference. */
576         for (i = 0; i < ds->ds_num; ++i) {
577                 tuple = PyTuple_New(4);
578                 PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
579                 PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
580                 PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min));
581                 PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max));
582                 PyList_SET_ITEM(list, i, tuple);
583         }
584         return list;
585 }
586
587 static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
588         int timeout = -1;
589         char *plugin = NULL, *identifier = NULL;
590         static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
591         
592         if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
593         Py_BEGIN_ALLOW_THREADS
594         plugin_flush(plugin, timeout, identifier);
595         Py_END_ALLOW_THREADS
596         PyMem_Free(plugin);
597         PyMem_Free(identifier);
598         Py_RETURN_NONE;
599 }
600
601 static PyObject *cpy_register_config(PyObject *self, PyObject *args, PyObject *kwds) {
602         return cpy_register_generic(&cpy_config_callbacks, args, kwds);
603 }
604
605 static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwds) {
606         return cpy_register_generic(&cpy_init_callbacks, args, kwds);
607 }
608
609 typedef int reg_function_t(const char *name, void *callback, void *data);
610
611 static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) {
612         char buf[512];
613         reg_function_t *register_function = (reg_function_t *) reg;
614         cpy_callback_t *c = NULL;
615         user_data_t *user_data = NULL;
616         char *name = NULL;
617         PyObject *callback = NULL, *data = NULL;
618         static char *kwlist[] = {"callback", "data", "name", NULL};
619         
620         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
621         if (PyCallable_Check(callback) == 0) {
622                 PyMem_Free(name);
623                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
624                 return NULL;
625         }
626         cpy_build_name(buf, sizeof(buf), callback, name);
627         PyMem_Free(name);
628         
629         Py_INCREF(callback);
630         Py_XINCREF(data);
631         c = malloc(sizeof(*c));
632         c->name = strdup(buf);
633         c->callback = callback;
634         c->data = data;
635         c->next = NULL;
636         user_data = malloc(sizeof(*user_data));
637         user_data->free_func = cpy_destroy_user_data;
638         user_data->data = c;
639         register_function(buf, handler, user_data);
640         return cpy_string_to_unicode_or_bytes(buf);
641 }
642
643 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
644         char buf[512];
645         cpy_callback_t *c = NULL;
646         user_data_t *user_data = NULL;
647         double interval = 0;
648         char *name = NULL;
649         PyObject *callback = NULL, *data = NULL;
650         static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
651         
652         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
653         if (PyCallable_Check(callback) == 0) {
654                 PyMem_Free(name);
655                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
656                 return NULL;
657         }
658         cpy_build_name(buf, sizeof(buf), callback, name);
659         PyMem_Free(name);
660         
661         Py_INCREF(callback);
662         Py_XINCREF(data);
663         c = malloc(sizeof(*c));
664         c->name = strdup(buf);
665         c->callback = callback;
666         c->data = data;
667         c->next = NULL;
668         user_data = malloc(sizeof(*user_data));
669         user_data->free_func = cpy_destroy_user_data;
670         user_data->data = c;
671         plugin_register_complex_read(/* group = */ NULL, buf,
672                         cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), user_data);
673         return cpy_string_to_unicode_or_bytes(buf);
674 }
675
676 static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
677         return cpy_register_generic_userdata((void *) plugin_register_log,
678                         (void *) cpy_log_callback, args, kwds);
679 }
680
681 static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) {
682         return cpy_register_generic_userdata((void *) plugin_register_write,
683                         (void *) cpy_write_callback, args, kwds);
684 }
685
686 static PyObject *cpy_register_notification(PyObject *self, PyObject *args, PyObject *kwds) {
687         return cpy_register_generic_userdata((void *) plugin_register_notification,
688                         (void *) cpy_notification_callback, args, kwds);
689 }
690
691 static PyObject *cpy_register_flush(PyObject *self, PyObject *args, PyObject *kwds) {
692         return cpy_register_generic_userdata((void *) plugin_register_flush,
693                         (void *) cpy_flush_callback, args, kwds);
694 }
695
696 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) {
697         return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
698 }
699
700 static PyObject *cpy_error(PyObject *self, PyObject *args) {
701         char *text;
702         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
703         Py_BEGIN_ALLOW_THREADS
704         plugin_log(LOG_ERR, "%s", text);
705         Py_END_ALLOW_THREADS
706         PyMem_Free(text);
707         Py_RETURN_NONE;
708 }
709
710 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
711         char *text;
712         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
713         Py_BEGIN_ALLOW_THREADS
714         plugin_log(LOG_WARNING, "%s", text);
715         Py_END_ALLOW_THREADS
716         PyMem_Free(text);
717         Py_RETURN_NONE;
718 }
719
720 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
721         char *text;
722         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
723         Py_BEGIN_ALLOW_THREADS
724         plugin_log(LOG_NOTICE, "%s", text);
725         Py_END_ALLOW_THREADS
726         PyMem_Free(text);
727         Py_RETURN_NONE;
728 }
729
730 static PyObject *cpy_info(PyObject *self, PyObject *args) {
731         char *text;
732         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
733         Py_BEGIN_ALLOW_THREADS
734         plugin_log(LOG_INFO, "%s", text);
735         Py_END_ALLOW_THREADS
736         PyMem_Free(text);
737         Py_RETURN_NONE;
738 }
739
740 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
741 #ifdef COLLECT_DEBUG
742         char *text;
743         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
744         Py_BEGIN_ALLOW_THREADS
745         plugin_log(LOG_DEBUG, "%s", text);
746         Py_END_ALLOW_THREADS
747         PyMem_Free(text);
748 #endif
749         Py_RETURN_NONE;
750 }
751
752 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *arg, const char *desc) {
753         char buf[512];
754         const char *name;
755         cpy_callback_t *prev = NULL, *tmp;
756
757         Py_INCREF(arg);
758         name = cpy_unicode_or_bytes_to_string(&arg);
759         if (name == NULL) {
760                 PyErr_Clear();
761                 if (!PyCallable_Check(arg)) {
762                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
763                         Py_DECREF(arg);
764                         return NULL;
765                 }
766                 cpy_build_name(buf, sizeof(buf), arg, NULL);
767                 name = buf;
768         }
769         for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
770                 if (strcmp(name, tmp->name) == 0)
771                         break;
772         
773         Py_DECREF(arg);
774         if (tmp == NULL) {
775                 PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
776                 return NULL;
777         }
778         /* Yes, this is actually save. To call this function the caller has to
779          * hold the GIL. Well, save as long as there is only one GIL anyway ... */
780         if (prev == NULL)
781                 *list_head = tmp->next;
782         else
783                 prev->next = tmp->next;
784         cpy_destroy_user_data(tmp);
785         Py_RETURN_NONE;
786 }
787
788 typedef int cpy_unregister_function_t(const char *name);
789
790 static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
791         char buf[512];
792         const char *name;
793
794         Py_INCREF(arg);
795         name = cpy_unicode_or_bytes_to_string(&arg);
796         if (name == NULL) {
797                 PyErr_Clear();
798                 if (!PyCallable_Check(arg)) {
799                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
800                         Py_DECREF(arg);
801                         return NULL;
802                 }
803                 cpy_build_name(buf, sizeof(buf), arg, NULL);
804                 name = buf;
805         }
806         if (unreg(name) == 0) {
807                 Py_DECREF(arg);
808                 Py_RETURN_NONE;
809         }
810         PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
811         Py_DECREF(arg);
812         return NULL;
813 }
814
815 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
816         return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
817 }
818
819 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
820         return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
821 }
822
823 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
824         return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
825 }
826
827 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
828         return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
829 }
830
831 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
832         return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
833 }
834
835 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
836         return cpy_unregister_generic_userdata(plugin_unregister_notification, arg, "notification");
837 }
838
839 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
840         return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
841 }
842
843 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
844         return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
845 }
846
847 static PyMethodDef cpy_methods[] = {
848         {"debug", cpy_debug, METH_VARARGS, log_doc},
849         {"info", cpy_info, METH_VARARGS, log_doc},
850         {"notice", cpy_notice, METH_VARARGS, log_doc},
851         {"warning", cpy_warning, METH_VARARGS, log_doc},
852         {"error", cpy_error, METH_VARARGS, log_doc},
853         {"get_dataset", (PyCFunction) cpy_get_dataset, METH_VARARGS, get_ds_doc},
854         {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
855         {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
856         {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
857         {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, reg_config_doc},
858         {"register_read", (PyCFunction) cpy_register_read, METH_VARARGS | METH_KEYWORDS, reg_read_doc},
859         {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, reg_write_doc},
860         {"register_notification", (PyCFunction) cpy_register_notification, METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
861         {"register_flush", (PyCFunction) cpy_register_flush, METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
862         {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
863         {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
864         {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
865         {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
866         {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
867         {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
868         {"unregister_notification", cpy_unregister_notification, METH_O, unregister_doc},
869         {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
870         {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
871         {0, 0, 0, 0}
872 };
873
874 static int cpy_shutdown(void) {
875         cpy_callback_t *c;
876         PyObject *ret;
877         
878         /* This can happen if the module was loaded but not configured. */
879         if (state != NULL)
880                 PyEval_RestoreThread(state);
881
882         for (c = cpy_shutdown_callbacks; c; c = c->next) {
883                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
884                 if (ret == NULL)
885                         cpy_log_exception("shutdown callback");
886                 else
887                         Py_DECREF(ret);
888         }
889         PyErr_Print();
890         Py_Finalize();
891         return 0;
892 }
893
894 static void cpy_int_handler(int sig) {
895         return;
896 }
897
898 static void *cpy_interactive(void *data) {
899         sigset_t sigset;
900         struct sigaction sig_int_action, old;
901         
902         /* Signal handler in a plugin? Bad stuff, but the best way to
903          * handle it I guess. In an interactive session people will
904          * press Ctrl+C at some time, which will generate a SIGINT.
905          * This will cause collectd to shutdown, thus killing the
906          * interactive interpreter, and leaving the terminal in a
907          * mess. Chances are, this isn't what the user wanted to do.
908          * 
909          * So this is the plan:
910          * 1. Block SIGINT in the main thread.
911          * 2. Install our own signal handler that does nothing.
912          * 3. Unblock SIGINT in the interactive thread.
913          *
914          * This will make sure that SIGINT won't kill collectd but
915          * still interrupt syscalls like sleep and pause.
916          * It does not raise a KeyboardInterrupt exception because so
917          * far nobody managed to figure out how to do that. */
918         memset (&sig_int_action, '\0', sizeof (sig_int_action));
919         sig_int_action.sa_handler = cpy_int_handler;
920         sigaction (SIGINT, &sig_int_action, &old);
921         
922         sigemptyset(&sigset);
923         sigaddset(&sigset, SIGINT);
924         pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
925         PyEval_AcquireThread(state);
926         if (PyImport_ImportModule("readline") == NULL) {
927                 /* This interactive session will suck. */
928                 cpy_log_exception("interactive session init");
929         }
930         PyRun_InteractiveLoop(stdin, "<stdin>");
931         PyErr_Print();
932         PyEval_ReleaseThread(state);
933         NOTICE("python: Interactive interpreter exited, stopping collectd ...");
934         /* Restore the original collectd SIGINT handler and raise SIGINT.
935          * The main thread still has SIGINT blocked and there's nothing we
936          * can do about that so this thread will handle it. But that's not
937          * important, except that it won't interrupt the main loop and so
938          * it might take a few seconds before collectd really shuts down. */
939         sigaction (SIGINT, &old, NULL);
940         raise(SIGINT);
941         pause();
942         return NULL;
943 }
944
945 static int cpy_init(void) {
946         cpy_callback_t *c;
947         PyObject *ret;
948         static pthread_t thread;
949         sigset_t sigset;
950         
951         if (!Py_IsInitialized()) {
952                 WARNING("python: Plugin loaded but not configured.");
953                 plugin_unregister_shutdown("python");
954                 return 0;
955         }
956         PyEval_InitThreads();
957         /* Now it's finally OK to use python threads. */
958         for (c = cpy_init_callbacks; c; c = c->next) {
959                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
960                 if (ret == NULL)
961                         cpy_log_exception("init callback");
962                 else
963                         Py_DECREF(ret);
964         }
965         sigemptyset(&sigset);
966         sigaddset(&sigset, SIGINT);
967         pthread_sigmask(SIG_BLOCK, &sigset, NULL);
968         state = PyEval_SaveThread();
969         if (do_interactive) {
970                 if (plugin_thread_create(&thread, NULL, cpy_interactive, NULL)) {
971                         ERROR("python: Error creating thread for interactive interpreter.");
972                 }
973         }
974
975         return 0;
976 }
977
978 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
979         int i;
980         PyObject *item, *values, *children, *tmp;
981         
982         if (parent == NULL)
983                 parent = Py_None;
984         
985         values = PyTuple_New(ci->values_num); /* New reference. */
986         for (i = 0; i < ci->values_num; ++i) {
987                 if (ci->values[i].type == OCONFIG_TYPE_STRING) {
988                         PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
989                 } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
990                         PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
991                 } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
992                         PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
993                 }
994         }
995         
996         tmp = cpy_string_to_unicode_or_bytes(ci->key);
997         item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
998         if (item == NULL)
999                 return NULL;
1000         children = PyTuple_New(ci->children_num); /* New reference. */
1001         for (i = 0; i < ci->children_num; ++i) {
1002                 PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
1003         }
1004         tmp = ((Config *) item)->children;
1005         ((Config *) item)->children = children;
1006         Py_XDECREF(tmp);
1007         return item;
1008 }
1009
1010 #ifdef IS_PY3K
1011 static struct PyModuleDef collectdmodule = {
1012         PyModuleDef_HEAD_INIT,
1013         "collectd",   /* name of module */
1014         "The python interface to collectd", /* module documentation, may be NULL */
1015         -1,
1016         cpy_methods
1017 };
1018
1019 PyMODINIT_FUNC PyInit_collectd(void) {
1020         return PyModule_Create(&collectdmodule);
1021 }
1022 #endif
1023
1024 static int cpy_init_python() {
1025         PyObject *sys;
1026         PyObject *module;
1027
1028 #ifdef IS_PY3K
1029         wchar_t *argv = L"";
1030         /* Add a builtin module, before Py_Initialize */
1031         PyImport_AppendInittab("collectd", PyInit_collectd);
1032 #else
1033         char *argv = "";
1034 #endif
1035         
1036         Py_Initialize();
1037         
1038         PyType_Ready(&ConfigType);
1039         PyType_Ready(&PluginDataType);
1040         ValuesType.tp_base = &PluginDataType;
1041         PyType_Ready(&ValuesType);
1042         NotificationType.tp_base = &PluginDataType;
1043         PyType_Ready(&NotificationType);
1044         SignedType.tp_base = &PyLong_Type;
1045         PyType_Ready(&SignedType);
1046         UnsignedType.tp_base = &PyLong_Type;
1047         PyType_Ready(&UnsignedType);
1048         sys = PyImport_ImportModule("sys"); /* New reference. */
1049         if (sys == NULL) {
1050                 cpy_log_exception("python initialization");
1051                 return 1;
1052         }
1053         sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1054         Py_DECREF(sys);
1055         if (sys_path == NULL) {
1056                 cpy_log_exception("python initialization");
1057                 return 1;
1058         }
1059         PySys_SetArgv(1, &argv);
1060         PyList_SetSlice(sys_path, 0, 1, NULL);
1061
1062 #ifdef IS_PY3K
1063         module = PyImport_ImportModule("collectd");
1064 #else
1065         module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1066 #endif
1067         PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
1068         PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
1069         PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
1070         PyModule_AddObject(module, "Signed", (void *) &SignedType); /* Steals a reference. */
1071         PyModule_AddObject(module, "Unsigned", (void *) &UnsignedType); /* Steals a reference. */
1072         PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1073         PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1074         PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1075         PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1076         PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1077         PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1078         PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1079         PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1080         PyModule_AddStringConstant(module, "DS_TYPE_COUNTER", DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1081         PyModule_AddStringConstant(module, "DS_TYPE_GAUGE", DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1082         PyModule_AddStringConstant(module, "DS_TYPE_DERIVE", DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1083         PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE", DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1084         return 0;
1085 }
1086
1087 static int cpy_config(oconfig_item_t *ci) {
1088         int i;
1089         PyObject *tb;
1090
1091         /* Ok in theory we shouldn't do initialization at this point
1092          * but we have to. In order to give python scripts a chance
1093          * to register a config callback we need to be able to execute
1094          * python code during the config callback so we have to start
1095          * the interpreter here. */
1096         /* Do *not* use the python "thread" module at this point! */
1097
1098         if (!Py_IsInitialized() && cpy_init_python()) return 1;
1099
1100         for (i = 0; i < ci->children_num; ++i) {
1101                 oconfig_item_t *item = ci->children + i;
1102                 
1103                 if (strcasecmp(item->key, "Interactive") == 0) {
1104                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
1105                                 continue;
1106                         do_interactive = item->values[0].value.boolean;
1107                 } else if (strcasecmp(item->key, "Encoding") == 0) {
1108                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
1109                                 continue;
1110 #ifdef IS_PY3K
1111                         NOTICE("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings. Ignoring this.");
1112 #else
1113                         /* Why is this even necessary? And undocumented? */
1114                         if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
1115                                 cpy_log_exception("setting default encoding");
1116 #endif
1117                 } else if (strcasecmp(item->key, "LogTraces") == 0) {
1118                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
1119                                 continue;
1120                         if (!item->values[0].value.boolean) {
1121                                 Py_XDECREF(cpy_format_exception);
1122                                 cpy_format_exception = NULL;
1123                                 continue;
1124                         }
1125                         if (cpy_format_exception)
1126                                 continue;
1127                         tb = PyImport_ImportModule("traceback"); /* New reference. */
1128                         if (tb == NULL) {
1129                                 cpy_log_exception("python initialization");
1130                                 continue;
1131                         }
1132                         cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1133                         Py_DECREF(tb);
1134                         if (cpy_format_exception == NULL)
1135                                 cpy_log_exception("python initialization");
1136                 } else if (strcasecmp(item->key, "ModulePath") == 0) {
1137                         char *dir = NULL;
1138                         PyObject *dir_object;
1139                         
1140                         if (cf_util_get_string(item, &dir) != 0) 
1141                                 continue;
1142                         dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1143                         if (dir_object == NULL) {
1144                                 ERROR("python plugin: Unable to convert \"%s\" to "
1145                                       "a python object.", dir);
1146                                 free(dir);
1147                                 cpy_log_exception("python initialization");
1148                                 continue;
1149                         }
1150                         if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1151                                 ERROR("python plugin: Unable to prepend \"%s\" to "
1152                                       "python module path.", dir);
1153                                 cpy_log_exception("python initialization");
1154                         }
1155                         Py_DECREF(dir_object);
1156                         free(dir);
1157                 } else if (strcasecmp(item->key, "Import") == 0) {
1158                         char *module_name = NULL;
1159                         PyObject *module;
1160                         
1161                         if (cf_util_get_string(item, &module_name) != 0) 
1162                                 continue;
1163                         module = PyImport_ImportModule(module_name); /* New reference. */
1164                         if (module == NULL) {
1165                                 ERROR("python plugin: Error importing module \"%s\".", module_name);
1166                                 cpy_log_exception("importing module");
1167                         }
1168                         free(module_name);
1169                         Py_XDECREF(module);
1170                 } else if (strcasecmp(item->key, "Module") == 0) {
1171                         char *name = NULL;
1172                         cpy_callback_t *c;
1173                         PyObject *ret;
1174                         
1175                         if (cf_util_get_string(item, &name) != 0)
1176                                 continue;
1177                         for (c = cpy_config_callbacks; c; c = c->next) {
1178                                 if (strcasecmp(c->name + 7, name) == 0)
1179                                         break;
1180                         }
1181                         if (c == NULL) {
1182                                 WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1183                                         "but the plugin isn't loaded or didn't register "
1184                                         "a configuration callback.", name);
1185                                 free(name);
1186                                 continue;
1187                         }
1188                         free(name);
1189                         if (c->data == NULL)
1190                                 ret = PyObject_CallFunction(c->callback, "N",
1191                                         cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1192                         else
1193                                 ret = PyObject_CallFunction(c->callback, "NO",
1194                                         cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
1195                         if (ret == NULL)
1196                                 cpy_log_exception("loading module");
1197                         else
1198                                 Py_DECREF(ret);
1199                 } else {
1200                         WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
1201                 }
1202         }
1203         return 0;
1204 }
1205
1206 void module_register(void) {
1207         plugin_register_complex_config("python", cpy_config);
1208         plugin_register_init("python", cpy_init);
1209         plugin_register_shutdown("python", cpy_shutdown);
1210 }