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