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