Merge branch 'collectd-4.9'
[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 flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
50                 "\n"
51                 "Flushes the cache of another plugin.";
52
53 static char unregister_doc[] = "Unregisters a callback. This function needs exactly one parameter either\n"
54                 "the function to unregister or the callback identifier to unregister.";
55
56 static char reg_log_doc[] = "register_log(callback[, data][, name]) -> identifier\n"
57                 "\n"
58                 "Register a callback function for log messages.\n"
59                 "\n"
60                 "'callback' is a callable object that will be called every time something\n"
61                 "    is logged.\n"
62                 "'data' is an optional object that will be passed back to the callback\n"
63                 "    function every time it is called.\n"
64                 "'name' is an optional identifier for this callback. The default name\n"
65                 "    is 'python.<module>'.\n"
66                 "    Every callback needs a unique identifier, so if you want to\n"
67                 "    register this callback multiple time from the same module you need\n"
68                 "    to specify a name here.\n"
69                 "'identifier' is the full identifier assigned to this callback.\n"
70                 "\n"
71                 "The callback function will be called with two or three parameters:\n"
72                 "severity: An integer that should be compared to the LOG_ constants.\n"
73                 "message: The text to be logged.\n"
74                 "data: The optional data parameter passed to the register function.\n"
75                 "    If the parameter was omitted it will be omitted here, too.";
76
77 static char reg_init_doc[] = "register_init(callback[, data][, name]) -> identifier\n"
78                 "\n"
79                 "Register a callback function that will be executed once after the config.\n"
80                 "file has been read, all plugins heve been loaded and the collectd has\n"
81                 "forked into the background.\n"
82                 "\n"
83                 "'callback' is a callable object that will be executed.\n"
84                 "'data' is an optional object that will be passed back to the callback\n"
85                 "    function when it is called.\n"
86                 "'name' is an optional identifier for this callback. The default name\n"
87                 "    is 'python.<module>'.\n"
88                 "    Every callback needs a unique identifier, so if you want to\n"
89                 "    register this callback multiple time from the same module you need\n"
90                 "    to specify a name here.\n"
91                 "'identifier' is the full identifier assigned to this callback.\n"
92                 "\n"
93                 "The callback function will be called without parameters, except for\n"
94                 "data if it was supplied.";
95
96 static char reg_config_doc[] = "register_config(callback[, data][, name]) -> identifier\n"
97                 "\n"
98                 "Register a callback function for config file entries.\n"
99                 "'callback' is a callable object that will be called for every config block.\n"
100                 "'data' is an optional object that will be passed back to the callback\n"
101                 "    function every time it is called.\n"
102                 "'name' is an optional identifier for this callback. The default name\n"
103                 "    is 'python.<module>'.\n"
104                 "    Every callback needs a unique identifier, so if you want to\n"
105                 "    register this callback multiple time from the same module you need\n"
106                 "    to specify a name here.\n"
107                 "'identifier' is the full identifier assigned to this callback.\n"
108                 "\n"
109                 "The callback function will be called with one or two parameters:\n"
110                 "config: A Config object.\n"
111                 "data: The optional data parameter passed to the register function.\n"
112                 "    If the parameter was omitted it will be omitted here, too.";
113
114 static char reg_read_doc[] = "register_read(callback[, interval][, data][, name]) -> identifier\n"
115                 "\n"
116                 "Register a callback function for reading data. It will just be called\n"
117                 "in a fixed interval to signal that it's time to dispatch new values.\n"
118                 "'callback' is a callable object that will be called every time something\n"
119                 "    is logged.\n"
120                 "'interval' is the number of seconds between between calls to the callback\n"
121                 "    function. Full float precision is supported here.\n"
122                 "'data' is an optional object that will be passed back to the callback\n"
123                 "    function every time it is called.\n"
124                 "'name' is an optional identifier for this callback. The default name\n"
125                 "    is 'python.<module>'.\n"
126                 "    Every callback needs a unique identifier, so if you want to\n"
127                 "    register this callback multiple time from the same module you need\n"
128                 "    to specify a name here.\n"
129                 "'identifier' is the full identifier assigned to this callback.\n"
130                 "\n"
131                 "The callback function will be called without parameters, except for\n"
132                 "data if it was supplied.";
133
134 static char reg_write_doc[] = "register_write(callback[, data][, name]) -> identifier\n"
135                 "\n"
136                 "Register a callback function to receive values dispatched by other plugins.\n"
137                 "'callback' is a callable object that will be called every time a value\n"
138                 "    is dispatched.\n"
139                 "'data' is an optional object that will be passed back to the callback\n"
140                 "    function every time it is called.\n"
141                 "'name' is an optional identifier for this callback. The default name\n"
142                 "    is 'python.<module>'.\n"
143                 "    Every callback needs a unique identifier, so if you want to\n"
144                 "    register this callback multiple time from the same module you need\n"
145                 "    to specify a name here.\n"
146                 "'identifier' is the full identifier assigned to this callback.\n"
147                 "\n"
148                 "The callback function will be called with one or two parameters:\n"
149                 "values: A Values object which is a copy of the dispatched values.\n"
150                 "data: The optional data parameter passed to the register function.\n"
151                 "    If the parameter was omitted it will be omitted here, too.";
152
153 static char reg_notification_doc[] = "register_notification(callback[, data][, name]) -> identifier\n"
154                 "\n"
155                 "Register a callback function for notifications.\n"
156                 "'callback' is a callable object that will be called every time a notification\n"
157                 "    is dispatched.\n"
158                 "'data' is an optional object that will be passed back to the callback\n"
159                 "    function every time it is called.\n"
160                 "'name' is an optional identifier for this callback. The default name\n"
161                 "    is 'python.<module>'.\n"
162                 "    Every callback needs a unique identifier, so if you want to\n"
163                 "    register this callback multiple time from the same module you need\n"
164                 "    to specify a name here.\n"
165                 "'identifier' is the full identifier assigned to this callback.\n"
166                 "\n"
167                 "The callback function will be called with one or two parameters:\n"
168                 "notification: A copy of the notification that was dispatched.\n"
169                 "data: The optional data parameter passed to the register function.\n"
170                 "    If the parameter was omitted it will be omitted here, too.";
171
172 static char reg_flush_doc[] = "register_flush(callback[, data][, name]) -> identifier\n"
173                 "\n"
174                 "Register a callback function for flush messages.\n"
175                 "'callback' is a callable object that will be called every time a plugin\n"
176                 "    requests a flush for either this or all plugins.\n"
177                 "'data' is an optional object that will be passed back to the callback\n"
178                 "    function every time it is called.\n"
179                 "'name' is an optional identifier for this callback. The default name\n"
180                 "    is 'python.<module>'.\n"
181                 "    Every callback needs a unique identifier, so if you want to\n"
182                 "    register this callback multiple time from the same module you need\n"
183                 "    to specify a name here.\n"
184                 "'identifier' is the full identifier assigned to this callback.\n"
185                 "\n"
186                 "The callback function will be called with two or three parameters:\n"
187                 "timeout: Indicates that only data older than 'timeout' seconds is to\n"
188                 "    be flushed.\n"
189                 "id: Specifies which values are to be flushed.\n"
190                 "data: The optional data parameter passed to the register function.\n"
191                 "    If the parameter was omitted it will be omitted here, too.";
192
193 static char reg_shutdown_doc[] = "register_shutdown(callback[, data][, name]) -> identifier\n"
194                 "\n"
195                 "Register a callback function for collectd shutdown.\n"
196                 "'callback' is a callable object that will be called once collectd is\n"
197                 "    shutting down.\n"
198                 "'data' is an optional object that will be passed back to the callback\n"
199                 "    function if it is called.\n"
200                 "'name' is an optional identifier for this callback. The default name\n"
201                 "    is 'python.<module>'.\n"
202                 "    Every callback needs a unique identifier, so if you want to\n"
203                 "    register this callback multiple time from the same module you need\n"
204                 "    to specify a name here.\n"
205                 "'identifier' is the full identifier assigned to this callback.\n"
206                 "\n"
207                 "The callback function will be called with no parameters except for\n"
208                 "    data if it was supplied.";
209
210
211 static int do_interactive = 0;
212
213 /* This is our global thread state. Python saves some stuff in thread-local
214  * storage. So if we allow the interpreter to run in the background
215  * (the scriptwriters might have created some threads from python), we have
216  * to save the state so we can resume it later after shutdown. */
217
218 static PyThreadState *state;
219
220 static PyObject *cpy_format_exception;
221
222 static cpy_callback_t *cpy_config_callbacks;
223 static cpy_callback_t *cpy_init_callbacks;
224 static cpy_callback_t *cpy_shutdown_callbacks;
225
226 static void cpy_destroy_user_data(void *data) {
227         cpy_callback_t *c = data;
228         free(c->name);
229         Py_DECREF(c->callback);
230         Py_XDECREF(c->data);
231         free(c);
232 }
233
234 /* You must hold the GIL to call this function!
235  * But if you managed to extract the callback parameter then you probably already do. */
236
237 static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) {
238         const char *module = NULL;
239         PyObject *mod = NULL;
240         
241         if (name != NULL) {
242                 snprintf(buf, size, "python.%s", name);
243                 return;
244         }
245         
246         mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
247         if (mod != NULL)
248                 module = cpy_unicode_or_bytes_to_string(&mod);
249         
250         if (module != NULL) {
251                 snprintf(buf, size, "python.%s", module);
252                 Py_XDECREF(mod);
253                 PyErr_Clear();
254                 return;
255         }
256         Py_XDECREF(mod);
257         
258         snprintf(buf, size, "python.%p", callback);
259         PyErr_Clear();
260 }
261
262 void cpy_log_exception(const char *context) {
263         int l = 0, i;
264         const char *typename = NULL, *message = NULL;
265         PyObject *type, *value, *traceback, *tn, *m, *list;
266         
267         PyErr_Fetch(&type, &value, &traceback);
268         PyErr_NormalizeException(&type, &value, &traceback);
269         if (type == NULL) return;
270         tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
271         m = PyObject_Str(value); /* New reference. */
272         if (tn != NULL)
273                 typename = cpy_unicode_or_bytes_to_string(&tn);
274         if (m != NULL)
275                 message = cpy_unicode_or_bytes_to_string(&m);
276         if (typename == NULL)
277                 typename = "NamelessException";
278         if (message == NULL)
279                 message = "N/A";
280         Py_BEGIN_ALLOW_THREADS
281         ERROR("Unhandled python exception in %s: %s: %s", context, typename, message);
282         Py_END_ALLOW_THREADS
283         Py_XDECREF(tn);
284         Py_XDECREF(m);
285         if (!cpy_format_exception) {
286                 PyErr_Clear();
287                 Py_XDECREF(type);
288                 Py_XDECREF(value);
289                 Py_XDECREF(traceback);
290                 return;
291         }
292         if (!traceback) {
293                 PyErr_Clear();
294                 return;
295         }
296         list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. */
297         if (list)
298                 l = PyObject_Length(list);
299         for (i = 0; i < l; ++i) {
300                 char *s;
301                 PyObject *line;
302                 
303                 line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
304                 Py_INCREF(line);
305                 s = strdup(cpy_unicode_or_bytes_to_string(&line));
306                 Py_DECREF(line);
307                 if (s[strlen(s) - 1] == '\n')
308                         s[strlen(s) - 1] = 0;
309                 Py_BEGIN_ALLOW_THREADS
310                 ERROR("%s", s);
311                 Py_END_ALLOW_THREADS
312                 free(s);
313         }
314         Py_XDECREF(list);
315         PyErr_Clear();
316 }
317
318 static int cpy_read_callback(user_data_t *data) {
319         cpy_callback_t *c = data->data;
320         PyObject *ret;
321
322         CPY_LOCK_THREADS
323                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
324                 if (ret == NULL) {
325                         cpy_log_exception("read callback");
326                 } else {
327                         Py_DECREF(ret);
328                 }
329         CPY_RELEASE_THREADS
330         if (ret == NULL)
331                 return 1;
332         return 0;
333 }
334
335 static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
336         int i;
337         cpy_callback_t *c = data->data;
338         PyObject *ret, *list, *temp, *dict = NULL;
339         Values *v;
340
341         CPY_LOCK_THREADS
342                 list = PyList_New(value_list->values_len); /* New reference. */
343                 if (list == NULL) {
344                         cpy_log_exception("write callback");
345                         CPY_RETURN_FROM_THREADS 0;
346                 }
347                 for (i = 0; i < value_list->values_len; ++i) {
348                         if (ds->ds->type == DS_TYPE_COUNTER) {
349                                 if ((long) value_list->values[i].counter == value_list->values[i].counter)
350                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
351                                 else
352                                         PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
353                         } else if (ds->ds->type == DS_TYPE_GAUGE) {
354                                 PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
355                         } else if (ds->ds->type == DS_TYPE_DERIVE) {
356                                 if ((long) value_list->values[i].derive == value_list->values[i].derive)
357                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
358                                 else
359                                         PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
360                         } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
361                                 if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
362                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
363                                 else
364                                         PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
365                         } else {
366                                 Py_BEGIN_ALLOW_THREADS
367                                 ERROR("cpy_write_callback: Unknown value type %d.", ds->ds->type);
368                                 Py_END_ALLOW_THREADS
369                                 Py_DECREF(list);
370                                 CPY_RETURN_FROM_THREADS 0;
371                         }
372                         if (PyErr_Occurred() != NULL) {
373                                 cpy_log_exception("value building for write callback");
374                                 CPY_RETURN_FROM_THREADS 0;
375                         }
376                 }
377                 dict = PyDict_New();
378                 if (value_list->meta) {
379                         int i, num;
380                         char **table;
381                         meta_data_t *meta = value_list->meta;
382
383                         num = meta_data_toc(meta, &table);
384                         for (i = 0; i < num; ++i) {
385                                 int type;
386                                 char *string;
387                                 int64_t si;
388                                 uint64_t ui;
389                                 double d;
390                                 _Bool b;
391                                 
392                                 type = meta_data_type(meta, table[i]);
393                                 if (type == MD_TYPE_STRING) {
394                                         if (meta_data_get_string(meta, table[i], &string))
395                                                 continue;
396                                         temp = cpy_string_to_unicode_or_bytes(string);
397                                         free(string);
398                                         PyDict_SetItemString(dict, table[i], temp);
399                                         Py_XDECREF(temp);
400                                 } else if (type == MD_TYPE_SIGNED_INT) {
401                                         if (meta_data_get_signed_int(meta, table[i], &si))
402                                                 continue;
403                                         temp = PyObject_CallFunctionObjArgs((void *) &SignedType, PyLong_FromLongLong(si), (void *) 0);
404                                         PyDict_SetItemString(dict, table[i], temp);
405                                         Py_XDECREF(temp);
406                                 } else if (type == MD_TYPE_UNSIGNED_INT) {
407                                         if (meta_data_get_unsigned_int(meta, table[i], &ui))
408                                                 continue;
409                                         temp = PyObject_CallFunctionObjArgs((void *) &UnsignedType, PyLong_FromUnsignedLongLong(ui), (void *) 0);
410                                         PyDict_SetItemString(dict, table[i], temp);
411                                         Py_XDECREF(temp);
412                                 } else if (type == MD_TYPE_DOUBLE) {
413                                         if (meta_data_get_double(meta, table[i], &d))
414                                                 continue;
415                                         temp = PyFloat_FromDouble(d);
416                                         PyDict_SetItemString(dict, table[i], temp);
417                                         Py_XDECREF(temp);
418                                 } else if (type == MD_TYPE_BOOLEAN) {
419                                         if (meta_data_get_boolean(meta, table[i], &b))
420                                                 continue;
421                                         if (b)
422                                                 PyDict_SetItemString(dict, table[i], Py_True);
423                                         else
424                                                 PyDict_SetItemString(dict, table[i], Py_False);
425                                 }
426                                 free(table[i]);
427                         }
428                         free(table);
429                 }
430                 v = PyObject_New(Values, (void *) &ValuesType);
431                 sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
432                 sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
433                 sstrncpy(v->data.type_instance, value_list->type_instance, sizeof(v->data.type_instance));
434                 sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
435                 sstrncpy(v->data.plugin_instance, value_list->plugin_instance, sizeof(v->data.plugin_instance));
436                 v->data.time = value_list->time;
437                 v->interval = value_list->interval;
438                 v->values = list;
439                 v->meta = dict;
440                 ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
441                 if (ret == NULL) {
442                         cpy_log_exception("write callback");
443                 } else {
444                         Py_DECREF(ret);
445                 }
446         CPY_RELEASE_THREADS
447         return 0;
448 }
449
450 static int cpy_notification_callback(const notification_t *notification, user_data_t *data) {
451         cpy_callback_t *c = data->data;
452         PyObject *ret;
453         Notification *n;
454
455         CPY_LOCK_THREADS
456                 n = PyObject_New(Notification, (void *) &NotificationType);
457                 sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
458                 sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
459                 sstrncpy(n->data.type_instance, notification->type_instance, sizeof(n->data.type_instance));
460                 sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
461                 sstrncpy(n->data.plugin_instance, notification->plugin_instance, sizeof(n->data.plugin_instance));
462                 n->data.time = notification->time;
463                 sstrncpy(n->message, notification->message, sizeof(n->message));
464                 n->severity = notification->severity;
465                 ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
466                 if (ret == NULL) {
467                         cpy_log_exception("notification callback");
468                 } else {
469                         Py_DECREF(ret);
470                 }
471         CPY_RELEASE_THREADS
472         return 0;
473 }
474
475 static void cpy_log_callback(int severity, const char *message, user_data_t *data) {
476         cpy_callback_t * c = data->data;
477         PyObject *ret, *text;
478
479         CPY_LOCK_THREADS
480         text = cpy_string_to_unicode_or_bytes(message);
481         if (c->data == NULL)
482                 ret = PyObject_CallFunction(c->callback, "iN", severity, text); /* New reference. */
483         else
484                 ret = PyObject_CallFunction(c->callback, "iNO", severity, text, c->data); /* New reference. */
485
486         if (ret == NULL) {
487                 /* FIXME */
488                 /* Do we really want to trigger a log callback because a log callback failed?
489                  * Probably not. */
490                 PyErr_Print();
491                 /* In case someone wanted to be clever, replaced stderr and failed at that. */
492                 PyErr_Clear();
493         } else {
494                 Py_DECREF(ret);
495         }
496         CPY_RELEASE_THREADS
497 }
498
499 static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
500         cpy_callback_t * c = data->data;
501         PyObject *ret, *text;
502
503         CPY_LOCK_THREADS
504         text = cpy_string_to_unicode_or_bytes(id);
505         if (c->data == NULL)
506                 ret = PyObject_CallFunction(c->callback, "iN", timeout, text); /* New reference. */
507         else
508                 ret = PyObject_CallFunction(c->callback, "iNO", timeout, text, c->data); /* New reference. */
509
510         if (ret == NULL) {
511                 cpy_log_exception("flush callback");
512         } else {
513                 Py_DECREF(ret);
514         }
515         CPY_RELEASE_THREADS
516 }
517
518 static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
519         char buf[512];
520         cpy_callback_t *c;
521         const char *name = NULL;
522         PyObject *callback = NULL, *data = NULL, *mod = NULL;
523         static char *kwlist[] = {"callback", "data", "name", NULL};
524         
525         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
526         if (PyCallable_Check(callback) == 0) {
527                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
528                 return NULL;
529         }
530         cpy_build_name(buf, sizeof(buf), callback, name);
531
532         Py_INCREF(callback);
533         Py_XINCREF(data);
534         c = malloc(sizeof(*c));
535         c->name = strdup(buf);
536         c->callback = callback;
537         c->data = data;
538         c->next = *list_head;
539         *list_head = c;
540         Py_XDECREF(mod);
541         return cpy_string_to_unicode_or_bytes(buf);
542 }
543
544 static PyObject *cpy_flush(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
545         int timeout = -1;
546         const char *plugin = NULL, *identifier = NULL;
547         static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
548         
549         if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
550         Py_BEGIN_ALLOW_THREADS
551         plugin_flush(plugin, timeout, identifier);
552         Py_END_ALLOW_THREADS
553         Py_RETURN_NONE;
554 }
555
556 static PyObject *cpy_register_config(PyObject *self, PyObject *args, PyObject *kwds) {
557         return cpy_register_generic(&cpy_config_callbacks, args, kwds);
558 }
559
560 static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwds) {
561         return cpy_register_generic(&cpy_init_callbacks, args, kwds);
562 }
563
564 typedef int reg_function_t(const char *name, void *callback, void *data);
565
566 static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) {
567         char buf[512];
568         reg_function_t *register_function = (reg_function_t *) reg;
569         cpy_callback_t *c = NULL;
570         user_data_t *user_data = NULL;
571         const char *name = NULL;
572         PyObject *callback = NULL, *data = NULL;
573         static char *kwlist[] = {"callback", "data", "name", NULL};
574         
575         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
576         if (PyCallable_Check(callback) == 0) {
577                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
578                 return NULL;
579         }
580         cpy_build_name(buf, sizeof(buf), callback, name);
581         
582         Py_INCREF(callback);
583         Py_XINCREF(data);
584         c = malloc(sizeof(*c));
585         c->name = strdup(buf);
586         c->callback = callback;
587         c->data = data;
588         c->next = NULL;
589         user_data = malloc(sizeof(*user_data));
590         user_data->free_func = cpy_destroy_user_data;
591         user_data->data = c;
592         register_function(buf, handler, user_data);
593         return cpy_string_to_unicode_or_bytes(buf);
594 }
595
596 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
597         char buf[512];
598         cpy_callback_t *c = NULL;
599         user_data_t *user_data = NULL;
600         double interval = 0;
601         const char *name = NULL;
602         PyObject *callback = NULL, *data = NULL;
603         struct timespec ts;
604         static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
605         
606         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
607         if (PyCallable_Check(callback) == 0) {
608                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
609                 return NULL;
610         }
611         cpy_build_name(buf, sizeof(buf), callback, name);
612         
613         Py_INCREF(callback);
614         Py_XINCREF(data);
615         c = malloc(sizeof(*c));
616         c->name = strdup(buf);
617         c->callback = callback;
618         c->data = data;
619         c->next = NULL;
620         user_data = malloc(sizeof(*user_data));
621         user_data->free_func = cpy_destroy_user_data;
622         user_data->data = c;
623         ts.tv_sec = interval;
624         ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
625         plugin_register_complex_read(/* group = */ NULL, buf,
626                         cpy_read_callback, &ts, user_data);
627         return cpy_string_to_unicode_or_bytes(buf);
628 }
629
630 static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
631         return cpy_register_generic_userdata((void *) plugin_register_log,
632                         (void *) cpy_log_callback, args, kwds);
633 }
634
635 static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) {
636         return cpy_register_generic_userdata((void *) plugin_register_write,
637                         (void *) cpy_write_callback, args, kwds);
638 }
639
640 static PyObject *cpy_register_notification(PyObject *self, PyObject *args, PyObject *kwds) {
641         return cpy_register_generic_userdata((void *) plugin_register_notification,
642                         (void *) cpy_notification_callback, args, kwds);
643 }
644
645 static PyObject *cpy_register_flush(PyObject *self, PyObject *args, PyObject *kwds) {
646         return cpy_register_generic_userdata((void *) plugin_register_flush,
647                         (void *) cpy_flush_callback, args, kwds);
648 }
649
650 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) {
651         return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
652 }
653
654 static PyObject *cpy_error(PyObject *self, PyObject *args) {
655         const char *text;
656         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
657         Py_BEGIN_ALLOW_THREADS
658         plugin_log(LOG_ERR, "%s", text);
659         Py_END_ALLOW_THREADS
660         Py_RETURN_NONE;
661 }
662
663 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
664         const char *text;
665         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
666         Py_BEGIN_ALLOW_THREADS
667         plugin_log(LOG_WARNING, "%s", text);
668         Py_END_ALLOW_THREADS
669         Py_RETURN_NONE;
670 }
671
672 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
673         const char *text;
674         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
675         Py_BEGIN_ALLOW_THREADS
676         plugin_log(LOG_NOTICE, "%s", text);
677         Py_END_ALLOW_THREADS
678         Py_RETURN_NONE;
679 }
680
681 static PyObject *cpy_info(PyObject *self, PyObject *args) {
682         const char *text;
683         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
684         Py_BEGIN_ALLOW_THREADS
685         plugin_log(LOG_INFO, "%s", text);
686         Py_END_ALLOW_THREADS
687         Py_RETURN_NONE;
688 }
689
690 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
691 #ifdef COLLECT_DEBUG
692         const char *text;
693         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
694         Py_BEGIN_ALLOW_THREADS
695         plugin_log(LOG_DEBUG, "%s", text);
696         Py_END_ALLOW_THREADS
697 #endif
698         Py_RETURN_NONE;
699 }
700
701 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *arg, const char *desc) {
702         char buf[512];
703         const char *name;
704         cpy_callback_t *prev = NULL, *tmp;
705
706         Py_INCREF(arg);
707         name = cpy_unicode_or_bytes_to_string(&arg);
708         if (name == NULL) {
709                 PyErr_Clear();
710                 if (!PyCallable_Check(arg)) {
711                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
712                         Py_DECREF(arg);
713                         return NULL;
714                 }
715                 cpy_build_name(buf, sizeof(buf), arg, NULL);
716                 name = buf;
717         }
718         for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
719                 if (strcmp(name, tmp->name) == 0)
720                         break;
721         
722         Py_DECREF(arg);
723         if (tmp == NULL) {
724                 PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
725                 return NULL;
726         }
727         /* Yes, this is actually save. To call this function the caller has to
728          * hold the GIL. Well, save as long as there is only one GIL anyway ... */
729         if (prev == NULL)
730                 *list_head = tmp->next;
731         else
732                 prev->next = tmp->next;
733         cpy_destroy_user_data(tmp);
734         Py_RETURN_NONE;
735 }
736
737 typedef int cpy_unregister_function_t(const char *name);
738
739 static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
740         char buf[512];
741         const char *name;
742
743         Py_INCREF(arg);
744         name = cpy_unicode_or_bytes_to_string(&arg);
745         if (name == NULL) {
746                 PyErr_Clear();
747                 if (!PyCallable_Check(arg)) {
748                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
749                         Py_DECREF(arg);
750                         return NULL;
751                 }
752                 cpy_build_name(buf, sizeof(buf), arg, NULL);
753                 name = buf;
754         }
755         if (unreg(name) == 0) {
756                 Py_DECREF(arg);
757                 Py_RETURN_NONE;
758         }
759         PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
760         Py_DECREF(arg);
761         return NULL;
762 }
763
764 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
765         return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
766 }
767
768 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
769         return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
770 }
771
772 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
773         return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
774 }
775
776 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
777         return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
778 }
779
780 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
781         return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
782 }
783
784 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
785         return cpy_unregister_generic_userdata(plugin_unregister_notification, arg, "notification");
786 }
787
788 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
789         return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
790 }
791
792 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
793         return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
794 }
795
796 static PyMethodDef cpy_methods[] = {
797         {"debug", cpy_debug, METH_VARARGS, log_doc},
798         {"info", cpy_info, METH_VARARGS, log_doc},
799         {"notice", cpy_notice, METH_VARARGS, log_doc},
800         {"warning", cpy_warning, METH_VARARGS, log_doc},
801         {"error", cpy_error, METH_VARARGS, log_doc},
802         {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
803         {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
804         {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
805         {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, reg_config_doc},
806         {"register_read", (PyCFunction) cpy_register_read, METH_VARARGS | METH_KEYWORDS, reg_read_doc},
807         {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, reg_write_doc},
808         {"register_notification", (PyCFunction) cpy_register_notification, METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
809         {"register_flush", (PyCFunction) cpy_register_flush, METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
810         {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
811         {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
812         {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
813         {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
814         {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
815         {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
816         {"unregister_notification", cpy_unregister_notification, METH_O, unregister_doc},
817         {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
818         {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
819         {0, 0, 0, 0}
820 };
821
822 static int cpy_shutdown(void) {
823         cpy_callback_t *c;
824         PyObject *ret;
825         
826         /* This can happen if the module was loaded but not configured. */
827         if (state != NULL)
828                 PyEval_RestoreThread(state);
829
830         for (c = cpy_shutdown_callbacks; c; c = c->next) {
831                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
832                 if (ret == NULL)
833                         cpy_log_exception("shutdown callback");
834                 else
835                         Py_DECREF(ret);
836         }
837         PyErr_Print();
838         Py_Finalize();
839         return 0;
840 }
841
842 static void cpy_int_handler(int sig) {
843         return;
844 }
845
846 static void *cpy_interactive(void *data) {
847         sigset_t sigset;
848         struct sigaction sig_int_action, old;
849         
850         /* Signal handler in a plugin? Bad stuff, but the best way to
851          * handle it I guess. In an interactive session people will
852          * press Ctrl+C at some time, which will generate a SIGINT.
853          * This will cause collectd to shutdown, thus killing the
854          * interactive interpreter, and leaving the terminal in a
855          * mess. Chances are, this isn't what the user wanted to do.
856          * 
857          * So this is the plan:
858          * 1. Block SIGINT in the main thread.
859          * 2. Install our own signal handler that does nothing.
860          * 3. Unblock SIGINT in the interactive thread.
861          *
862          * This will make sure that SIGINT won't kill collectd but
863          * still interrupt syscalls like sleep and pause.
864          * It does not raise a KeyboardInterrupt exception because so
865          * far nobody managed to figure out how to do that. */
866         memset (&sig_int_action, '\0', sizeof (sig_int_action));
867         sig_int_action.sa_handler = cpy_int_handler;
868         sigaction (SIGINT, &sig_int_action, &old);
869         
870         sigemptyset(&sigset);
871         sigaddset(&sigset, SIGINT);
872         pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
873         PyEval_AcquireThread(state);
874         if (PyImport_ImportModule("readline") == NULL) {
875                 /* This interactive session will suck. */
876                 cpy_log_exception("interactive session init");
877         }
878         PyRun_InteractiveLoop(stdin, "<stdin>");
879         PyErr_Print();
880         PyEval_ReleaseThread(state);
881         NOTICE("python: Interactive interpreter exited, stopping collectd ...");
882         /* Restore the original collectd SIGINT handler and raise SIGINT.
883          * The main thread still has SIGINT blocked and there's nothing we
884          * can do about that so this thread will handle it. But that's not
885          * important, except that it won't interrupt the main loop and so
886          * it might take a few seconds before collectd really shuts down. */
887         sigaction (SIGINT, &old, NULL);
888         raise(SIGINT);
889         pause();
890         return NULL;
891 }
892
893 static int cpy_init(void) {
894         cpy_callback_t *c;
895         PyObject *ret;
896         static pthread_t thread;
897         sigset_t sigset;
898         
899         PyEval_InitThreads();
900         /* Now it's finally OK to use python threads. */
901         for (c = cpy_init_callbacks; c; c = c->next) {
902                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
903                 if (ret == NULL)
904                         cpy_log_exception("init callback");
905                 else
906                         Py_DECREF(ret);
907         }
908         sigemptyset(&sigset);
909         sigaddset(&sigset, SIGINT);
910         pthread_sigmask(SIG_BLOCK, &sigset, NULL);
911         state = PyEval_SaveThread();
912         if (do_interactive) {
913                 if (pthread_create(&thread, NULL, cpy_interactive, NULL)) {
914                         ERROR("python: Error creating thread for interactive interpreter.");
915                 }
916         }
917
918         return 0;
919 }
920
921 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
922         int i;
923         PyObject *item, *values, *children, *tmp;
924         
925         if (parent == NULL)
926                 parent = Py_None;
927         
928         values = PyTuple_New(ci->values_num); /* New reference. */
929         for (i = 0; i < ci->values_num; ++i) {
930                 if (ci->values[i].type == OCONFIG_TYPE_STRING) {
931                         PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
932                 } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
933                         PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
934                 } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
935                         PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
936                 }
937         }
938         
939         tmp = cpy_string_to_unicode_or_bytes(ci->key);
940         item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
941         if (item == NULL)
942                 return NULL;
943         children = PyTuple_New(ci->children_num); /* New reference. */
944         for (i = 0; i < ci->children_num; ++i) {
945                 PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
946         }
947         tmp = ((Config *) item)->children;
948         ((Config *) item)->children = children;
949         Py_XDECREF(tmp);
950         return item;
951 }
952
953 #ifdef IS_PY3K
954 static struct PyModuleDef collectdmodule = {
955         PyModuleDef_HEAD_INIT,
956         "collectd",   /* name of module */
957         "The python interface to collectd", /* module documentation, may be NULL */
958         -1,
959         cpy_methods
960 };
961
962 PyMODINIT_FUNC PyInit_collectd(void) {
963         return PyModule_Create(&collectdmodule);
964 }
965 #endif
966
967 static int cpy_config(oconfig_item_t *ci) {
968         int i;
969         PyObject *sys, *tb;
970         PyObject *sys_path;
971         PyObject *module;
972         
973         /* Ok in theory we shouldn't do initialization at this point
974          * but we have to. In order to give python scripts a chance
975          * to register a config callback we need to be able to execute
976          * python code during the config callback so we have to start
977          * the interpreter here. */
978         /* Do *not* use the python "thread" module at this point! */
979
980 #ifdef IS_PY3K
981         /* Add a builtin module, before Py_Initialize */
982         PyImport_AppendInittab("collectd", PyInit_collectd);
983 #endif
984         
985         Py_Initialize();
986         
987         PyType_Ready(&ConfigType);
988         PyType_Ready(&PluginDataType);
989         ValuesType.tp_base = &PluginDataType;
990         PyType_Ready(&ValuesType);
991         NotificationType.tp_base = &PluginDataType;
992         PyType_Ready(&NotificationType);
993         SignedType.tp_base = &PyLong_Type;
994         PyType_Ready(&SignedType);
995         UnsignedType.tp_base = &PyLong_Type;
996         PyType_Ready(&UnsignedType);
997         sys = PyImport_ImportModule("sys"); /* New reference. */
998         if (sys == NULL) {
999                 cpy_log_exception("python initialization");
1000                 return 1;
1001         }
1002         sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1003         Py_DECREF(sys);
1004         if (sys_path == NULL) {
1005                 cpy_log_exception("python initialization");
1006                 return 1;
1007         }
1008 #ifdef IS_PY3K
1009         module = PyImport_ImportModule("collectd");
1010 #else
1011         module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1012 #endif
1013         PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
1014         PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
1015         PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
1016         PyModule_AddObject(module, "Signed", (void *) &SignedType); /* Steals a reference. */
1017         PyModule_AddObject(module, "Unsigned", (void *) &UnsignedType); /* Steals a reference. */
1018         PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1019         PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1020         PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1021         PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1022         PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1023         PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1024         PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1025         PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1026         for (i = 0; i < ci->children_num; ++i) {
1027                 oconfig_item_t *item = ci->children + i;
1028                 
1029                 if (strcasecmp(item->key, "Interactive") == 0) {
1030                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
1031                                 continue;
1032                         do_interactive = item->values[0].value.boolean;
1033                 } else if (strcasecmp(item->key, "Encoding") == 0) {
1034                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
1035                                 continue;
1036                         /* Why is this even necessary? And undocumented? */
1037                         if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
1038                                 cpy_log_exception("setting default encoding");
1039                 } else if (strcasecmp(item->key, "LogTraces") == 0) {
1040                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
1041                                 continue;
1042                         if (!item->values[0].value.boolean) {
1043                                 Py_XDECREF(cpy_format_exception);
1044                                 cpy_format_exception = NULL;
1045                                 continue;
1046                         }
1047                         if (cpy_format_exception)
1048                                 continue;
1049                         tb = PyImport_ImportModule("traceback"); /* New reference. */
1050                         if (tb == NULL) {
1051                                 cpy_log_exception("python initialization");
1052                                 continue;
1053                         }
1054                         cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1055                         Py_DECREF(tb);
1056                         if (cpy_format_exception == NULL)
1057                                 cpy_log_exception("python initialization");
1058                 } else if (strcasecmp(item->key, "ModulePath") == 0) {
1059                         char *dir = NULL;
1060                         PyObject *dir_object;
1061                         
1062                         if (cf_util_get_string(item, &dir) != 0) 
1063                                 continue;
1064                         dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1065                         if (dir_object == NULL) {
1066                                 ERROR("python plugin: Unable to convert \"%s\" to "
1067                                       "a python object.", dir);
1068                                 free(dir);
1069                                 cpy_log_exception("python initialization");
1070                                 continue;
1071                         }
1072                         if (PyList_Append(sys_path, dir_object) != 0) {
1073                                 ERROR("python plugin: Unable to append \"%s\" to "
1074                                       "python module path.", dir);
1075                                 cpy_log_exception("python initialization");
1076                         }
1077                         Py_DECREF(dir_object);
1078                         free(dir);
1079                 } else if (strcasecmp(item->key, "Import") == 0) {
1080                         char *module_name = NULL;
1081                         PyObject *module;
1082                         
1083                         if (cf_util_get_string(item, &module_name) != 0) 
1084                                 continue;
1085                         module = PyImport_ImportModule(module_name); /* New reference. */
1086                         if (module == NULL) {
1087                                 ERROR("python plugin: Error importing module \"%s\".", module_name);
1088                                 cpy_log_exception("importing module");
1089                         }
1090                         free(module_name);
1091                         Py_XDECREF(module);
1092                 } else if (strcasecmp(item->key, "Module") == 0) {
1093                         char *name = NULL;
1094                         cpy_callback_t *c;
1095                         PyObject *ret;
1096                         
1097                         if (cf_util_get_string(item, &name) != 0)
1098                                 continue;
1099                         for (c = cpy_config_callbacks; c; c = c->next) {
1100                                 if (strcasecmp(c->name + 7, name) == 0)
1101                                         break;
1102                         }
1103                         if (c == NULL) {
1104                                 WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1105                                         "but the plugin isn't loaded or didn't register "
1106                                         "a configuration callback.", name);
1107                                 free(name);
1108                                 continue;
1109                         }
1110                         free(name);
1111                         if (c->data == NULL)
1112                                 ret = PyObject_CallFunction(c->callback, "N",
1113                                         cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1114                         else
1115                                 ret = PyObject_CallFunction(c->callback, "NO",
1116                                         cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
1117                         if (ret == NULL)
1118                                 cpy_log_exception("loading module");
1119                         else
1120                                 Py_DECREF(ret);
1121                 } else {
1122                         WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
1123                 }
1124         }
1125         Py_DECREF(sys_path);
1126         return 0;
1127 }
1128
1129 void module_register(void) {
1130         plugin_register_complex_config("python", cpy_config);
1131         plugin_register_init("python", cpy_init);
1132         plugin_register_shutdown("python", cpy_shutdown);
1133 }