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