Merge remote-tracking branch 'github/pr/2277'
[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   register_function(buf, handler,
722                     &(user_data_t){
723                         .data = c, .free_func = cpy_destroy_user_data,
724                     });
725
726   ++cpy_num_callbacks;
727   return cpy_string_to_unicode_or_bytes(buf);
728 }
729
730 static PyObject *cpy_register_read(PyObject *self, PyObject *args,
731                                    PyObject *kwds) {
732   char buf[512];
733   cpy_callback_t *c = NULL;
734   double interval = 0;
735   char *name = NULL;
736   PyObject *callback = NULL, *data = NULL;
737   static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
738
739   if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback,
740                                   &interval, &data, NULL, &name) == 0)
741     return NULL;
742   if (PyCallable_Check(callback) == 0) {
743     PyMem_Free(name);
744     PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
745     return NULL;
746   }
747   cpy_build_name(buf, sizeof(buf), callback, name);
748   PyMem_Free(name);
749
750   Py_INCREF(callback);
751   Py_XINCREF(data);
752
753   c = calloc(1, sizeof(*c));
754   if (c == NULL)
755     return NULL;
756
757   c->name = strdup(buf);
758   c->callback = callback;
759   c->data = data;
760   c->next = NULL;
761
762   plugin_register_complex_read(
763       /* group = */ "python", buf, cpy_read_callback,
764       DOUBLE_TO_CDTIME_T(interval),
765       &(user_data_t){
766           .data = c, .free_func = cpy_destroy_user_data,
767       });
768   ++cpy_num_callbacks;
769   return cpy_string_to_unicode_or_bytes(buf);
770 }
771
772 static PyObject *cpy_register_log(PyObject *self, PyObject *args,
773                                   PyObject *kwds) {
774   return cpy_register_generic_userdata((void *)plugin_register_log,
775                                        (void *)cpy_log_callback, args, kwds);
776 }
777
778 static PyObject *cpy_register_write(PyObject *self, PyObject *args,
779                                     PyObject *kwds) {
780   return cpy_register_generic_userdata((void *)plugin_register_write,
781                                        (void *)cpy_write_callback, args, kwds);
782 }
783
784 static PyObject *cpy_register_notification(PyObject *self, PyObject *args,
785                                            PyObject *kwds) {
786   return cpy_register_generic_userdata((void *)plugin_register_notification,
787                                        (void *)cpy_notification_callback,
788                                        args, kwds);
789 }
790
791 static PyObject *cpy_register_flush(PyObject *self, PyObject *args,
792                                     PyObject *kwds) {
793   return cpy_register_generic_userdata((void *)plugin_register_flush,
794                                        (void *)cpy_flush_callback, args, kwds);
795 }
796
797 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args,
798                                        PyObject *kwds) {
799   return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
800 }
801
802 static PyObject *cpy_error(PyObject *self, PyObject *args) {
803   char *text;
804   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
805     return NULL;
806   Py_BEGIN_ALLOW_THREADS plugin_log(LOG_ERR, "%s", text);
807   Py_END_ALLOW_THREADS PyMem_Free(text);
808   Py_RETURN_NONE;
809 }
810
811 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
812   char *text;
813   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
814     return NULL;
815   Py_BEGIN_ALLOW_THREADS plugin_log(LOG_WARNING, "%s", text);
816   Py_END_ALLOW_THREADS PyMem_Free(text);
817   Py_RETURN_NONE;
818 }
819
820 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
821   char *text;
822   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
823     return NULL;
824   Py_BEGIN_ALLOW_THREADS plugin_log(LOG_NOTICE, "%s", text);
825   Py_END_ALLOW_THREADS PyMem_Free(text);
826   Py_RETURN_NONE;
827 }
828
829 static PyObject *cpy_info(PyObject *self, PyObject *args) {
830   char *text;
831   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
832     return NULL;
833   Py_BEGIN_ALLOW_THREADS plugin_log(LOG_INFO, "%s", text);
834   Py_END_ALLOW_THREADS PyMem_Free(text);
835   Py_RETURN_NONE;
836 }
837
838 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
839 #ifdef COLLECT_DEBUG
840   char *text;
841   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
842     return NULL;
843   Py_BEGIN_ALLOW_THREADS plugin_log(LOG_DEBUG, "%s", text);
844   Py_END_ALLOW_THREADS PyMem_Free(text);
845 #endif
846   Py_RETURN_NONE;
847 }
848
849 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head,
850                                         PyObject *arg, const char *desc) {
851   char buf[512];
852   const char *name;
853   cpy_callback_t *prev = NULL, *tmp;
854
855   Py_INCREF(arg);
856   name = cpy_unicode_or_bytes_to_string(&arg);
857   if (name == NULL) {
858     PyErr_Clear();
859     if (!PyCallable_Check(arg)) {
860       PyErr_SetString(PyExc_TypeError, "This function needs a string or a "
861                                        "callable object as its only "
862                                        "parameter.");
863       Py_DECREF(arg);
864       return NULL;
865     }
866     cpy_build_name(buf, sizeof(buf), arg, NULL);
867     name = buf;
868   }
869   for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
870     if (strcmp(name, tmp->name) == 0)
871       break;
872
873   Py_DECREF(arg);
874   if (tmp == NULL) {
875     PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.",
876                  desc, name);
877     return NULL;
878   }
879   /* Yes, this is actually safe. To call this function the caller has to
880    * hold the GIL. Well, safe as long as there is only one GIL anyway ... */
881   if (prev == NULL)
882     *list_head = tmp->next;
883   else
884     prev->next = tmp->next;
885   cpy_destroy_user_data(tmp);
886   Py_RETURN_NONE;
887 }
888
889 static void cpy_unregister_list(cpy_callback_t **list_head) {
890   cpy_callback_t *cur, *next;
891   for (cur = *list_head; cur; cur = next) {
892     next = cur->next;
893     cpy_destroy_user_data(cur);
894   }
895   *list_head = NULL;
896 }
897
898 typedef int cpy_unregister_function_t(const char *name);
899
900 static PyObject *
901 cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg,
902                                 const char *desc) {
903   char buf[512];
904   const char *name;
905
906   Py_INCREF(arg);
907   name = cpy_unicode_or_bytes_to_string(&arg);
908   if (name == NULL) {
909     PyErr_Clear();
910     if (!PyCallable_Check(arg)) {
911       PyErr_SetString(PyExc_TypeError, "This function needs a string or a "
912                                        "callable object as its only "
913                                        "parameter.");
914       Py_DECREF(arg);
915       return NULL;
916     }
917     cpy_build_name(buf, sizeof(buf), arg, NULL);
918     name = buf;
919   }
920   if (unreg(name) == 0) {
921     Py_DECREF(arg);
922     Py_RETURN_NONE;
923   }
924   PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.",
925                desc, name);
926   Py_DECREF(arg);
927   return NULL;
928 }
929
930 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
931   return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
932 }
933
934 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
935   return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
936 }
937
938 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
939   return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
940 }
941
942 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
943   return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
944 }
945
946 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
947   return cpy_unregister_generic_userdata(plugin_unregister_write, arg,
948                                          "write");
949 }
950
951 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
952   return cpy_unregister_generic_userdata(plugin_unregister_notification, arg,
953                                          "notification");
954 }
955
956 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
957   return cpy_unregister_generic_userdata(plugin_unregister_flush, arg,
958                                          "flush");
959 }
960
961 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
962   return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
963 }
964
965 static PyMethodDef cpy_methods[] = {
966     {"debug", cpy_debug, METH_VARARGS, log_doc},
967     {"info", cpy_info, METH_VARARGS, log_doc},
968     {"notice", cpy_notice, METH_VARARGS, log_doc},
969     {"warning", cpy_warning, METH_VARARGS, log_doc},
970     {"error", cpy_error, METH_VARARGS, log_doc},
971     {"get_dataset", (PyCFunction)cpy_get_dataset, METH_VARARGS, get_ds_doc},
972     {"flush", (PyCFunction)cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
973     {"register_log", (PyCFunction)cpy_register_log,
974      METH_VARARGS | METH_KEYWORDS, reg_log_doc},
975     {"register_init", (PyCFunction)cpy_register_init,
976      METH_VARARGS | METH_KEYWORDS, reg_init_doc},
977     {"register_config", (PyCFunction)cpy_register_config,
978      METH_VARARGS | METH_KEYWORDS, reg_config_doc},
979     {"register_read", (PyCFunction)cpy_register_read,
980      METH_VARARGS | METH_KEYWORDS, reg_read_doc},
981     {"register_write", (PyCFunction)cpy_register_write,
982      METH_VARARGS | METH_KEYWORDS, reg_write_doc},
983     {"register_notification", (PyCFunction)cpy_register_notification,
984      METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
985     {"register_flush", (PyCFunction)cpy_register_flush,
986      METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
987     {"register_shutdown", (PyCFunction)cpy_register_shutdown,
988      METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
989     {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
990     {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
991     {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
992     {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
993     {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
994     {"unregister_notification", cpy_unregister_notification, METH_O,
995      unregister_doc},
996     {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
997     {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
998     {0, 0, 0, 0}};
999
1000 static int cpy_shutdown(void) {
1001   PyObject *ret;
1002
1003   if (!state) {
1004     printf(
1005         "================================================================\n");
1006     printf(
1007         "collectd shutdown while running an interactive session. This will\n");
1008     printf("probably leave your terminal in a mess.\n");
1009     printf("Run the command \"reset\" to get it back into a usable state.\n");
1010     printf("You can press Ctrl+D in the interactive session to\n");
1011     printf("close collectd and avoid this problem in the future.\n");
1012     printf(
1013         "================================================================\n");
1014   }
1015
1016   CPY_LOCK_THREADS
1017
1018   for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
1019     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1020                                        (void *)0); /* New reference. */
1021     if (ret == NULL)
1022       cpy_log_exception("shutdown callback");
1023     else
1024       Py_DECREF(ret);
1025   }
1026   PyErr_Print();
1027
1028   Py_BEGIN_ALLOW_THREADS cpy_unregister_list(&cpy_config_callbacks);
1029   cpy_unregister_list(&cpy_init_callbacks);
1030   cpy_unregister_list(&cpy_shutdown_callbacks);
1031   cpy_shutdown_triggered = 1;
1032   Py_END_ALLOW_THREADS
1033
1034       if (!cpy_num_callbacks) {
1035     Py_Finalize();
1036     return 0;
1037   }
1038
1039   CPY_RELEASE_THREADS
1040   return 0;
1041 }
1042
1043 static void *cpy_interactive(void *pipefd) {
1044   PyOS_sighandler_t cur_sig;
1045
1046   /* Signal handler in a plugin? Bad stuff, but the best way to
1047    * handle it I guess. In an interactive session people will
1048    * press Ctrl+C at some time, which will generate a SIGINT.
1049    * This will cause collectd to shutdown, thus killing the
1050    * interactive interpreter, and leaving the terminal in a
1051    * mess. Chances are, this isn't what the user wanted to do.
1052    *
1053    * So this is the plan:
1054    * 1. Restore Python's own signal handler
1055    * 2. Tell Python we just forked so it will accept this thread
1056    *    as the main one. No version of Python will ever handle
1057    *    interrupts anywhere but in the main thread.
1058    * 3. After the interactive loop is done, restore collectd's
1059    *    SIGINT handler.
1060    * 4. Raise SIGINT for a clean shutdown. The signal is sent to
1061    *    the main thread to ensure it wakes up the main interval
1062    *    sleep so that collectd shuts down immediately not in 10
1063    *    seconds.
1064    *
1065    * This will make sure that SIGINT won't kill collectd but
1066    * still interrupt syscalls like sleep and pause. */
1067
1068   if (PyImport_ImportModule("readline") == NULL) {
1069     /* This interactive session will suck. */
1070     cpy_log_exception("interactive session init");
1071   }
1072   cur_sig = PyOS_setsig(SIGINT, python_sigint_handler);
1073   PyOS_AfterFork();
1074   PyEval_InitThreads();
1075   close(*(int *)pipefd);
1076   PyRun_InteractiveLoop(stdin, "<stdin>");
1077   PyOS_setsig(SIGINT, cur_sig);
1078   PyErr_Print();
1079   state = PyEval_SaveThread();
1080   NOTICE("python: Interactive interpreter exited, stopping collectd ...");
1081   pthread_kill(main_thread, SIGINT);
1082   return NULL;
1083 }
1084
1085 static int cpy_init(void) {
1086   PyObject *ret;
1087   int pipefd[2];
1088   char buf;
1089   static pthread_t thread;
1090
1091   if (!Py_IsInitialized()) {
1092     WARNING("python: Plugin loaded but not configured.");
1093     plugin_unregister_shutdown("python");
1094     Py_Finalize();
1095     return 0;
1096   }
1097   main_thread = pthread_self();
1098   if (do_interactive) {
1099     if (pipe(pipefd)) {
1100       ERROR("python: Unable to create pipe.");
1101       return 1;
1102     }
1103     if (plugin_thread_create(&thread, NULL, cpy_interactive, pipefd + 1,
1104                              "python interpreter")) {
1105       ERROR("python: Error creating thread for interactive interpreter.");
1106     }
1107     if (read(pipefd[0], &buf, 1))
1108       ;
1109     (void)close(pipefd[0]);
1110   } else {
1111     PyEval_InitThreads();
1112     state = PyEval_SaveThread();
1113   }
1114   CPY_LOCK_THREADS
1115   for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
1116     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1117                                        (void *)0); /* New reference. */
1118     if (ret == NULL)
1119       cpy_log_exception("init callback");
1120     else
1121       Py_DECREF(ret);
1122   }
1123   CPY_RELEASE_THREADS
1124
1125   return 0;
1126 }
1127
1128 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
1129   PyObject *item, *values, *children, *tmp;
1130
1131   if (parent == NULL)
1132     parent = Py_None;
1133
1134   values = PyTuple_New(ci->values_num); /* New reference. */
1135   for (int i = 0; i < ci->values_num; ++i) {
1136     if (ci->values[i].type == OCONFIG_TYPE_STRING) {
1137       PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(
1138                                       ci->values[i].value.string));
1139     } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
1140       PyTuple_SET_ITEM(values, i,
1141                        PyFloat_FromDouble(ci->values[i].value.number));
1142     } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
1143       PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
1144     }
1145   }
1146
1147   tmp = cpy_string_to_unicode_or_bytes(ci->key);
1148   item = PyObject_CallFunction((void *)&ConfigType, "NONO", tmp, parent, values,
1149                                Py_None);
1150   if (item == NULL)
1151     return NULL;
1152   children = PyTuple_New(ci->children_num); /* New reference. */
1153   for (int i = 0; i < ci->children_num; ++i) {
1154     PyTuple_SET_ITEM(children, i,
1155                      cpy_oconfig_to_pyconfig(ci->children + i, item));
1156   }
1157   tmp = ((Config *)item)->children;
1158   ((Config *)item)->children = children;
1159   Py_XDECREF(tmp);
1160   return item;
1161 }
1162
1163 #ifdef IS_PY3K
1164 static struct PyModuleDef collectdmodule = {
1165     PyModuleDef_HEAD_INIT, "collectd",  /* name of module */
1166     "The python interface to collectd", /* module documentation, may be NULL */
1167     -1, cpy_methods};
1168
1169 PyMODINIT_FUNC PyInit_collectd(void) {
1170   return PyModule_Create(&collectdmodule);
1171 }
1172 #endif
1173
1174 static int cpy_init_python(void) {
1175   PyOS_sighandler_t cur_sig;
1176   PyObject *sys;
1177   PyObject *module;
1178
1179 #ifdef IS_PY3K
1180   wchar_t *argv = L"";
1181   /* Add a builtin module, before Py_Initialize */
1182   PyImport_AppendInittab("collectd", PyInit_collectd);
1183 #else
1184   char *argv = "";
1185 #endif
1186
1187   /* Chances are the current signal handler is already SIG_DFL, but let's make
1188    * sure. */
1189   cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
1190   Py_Initialize();
1191   python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
1192
1193   PyType_Ready(&ConfigType);
1194   PyType_Ready(&PluginDataType);
1195   ValuesType.tp_base = &PluginDataType;
1196   PyType_Ready(&ValuesType);
1197   NotificationType.tp_base = &PluginDataType;
1198   PyType_Ready(&NotificationType);
1199   SignedType.tp_base = &PyLong_Type;
1200   PyType_Ready(&SignedType);
1201   UnsignedType.tp_base = &PyLong_Type;
1202   PyType_Ready(&UnsignedType);
1203   sys = PyImport_ImportModule("sys"); /* New reference. */
1204   if (sys == NULL) {
1205     cpy_log_exception("python initialization");
1206     return 1;
1207   }
1208   sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1209   Py_DECREF(sys);
1210   if (sys_path == NULL) {
1211     cpy_log_exception("python initialization");
1212     return 1;
1213   }
1214   PySys_SetArgv(1, &argv);
1215   PyList_SetSlice(sys_path, 0, 1, NULL);
1216
1217 #ifdef IS_PY3K
1218   module = PyImport_ImportModule("collectd");
1219 #else
1220   module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1221 #endif
1222   PyModule_AddObject(module, "Config",
1223                      (void *)&ConfigType); /* Steals a reference. */
1224   PyModule_AddObject(module, "Values",
1225                      (void *)&ValuesType); /* Steals a reference. */
1226   PyModule_AddObject(module, "Notification",
1227                      (void *)&NotificationType); /* Steals a reference. */
1228   PyModule_AddObject(module, "Signed",
1229                      (void *)&SignedType); /* Steals a reference. */
1230   PyModule_AddObject(module, "Unsigned",
1231                      (void *)&UnsignedType); /* Steals a reference. */
1232   PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1233   PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1234   PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1235   PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1236   PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1237   PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1238   PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1239   PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1240   PyModule_AddStringConstant(module, "DS_TYPE_COUNTER",
1241                              DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1242   PyModule_AddStringConstant(module, "DS_TYPE_GAUGE",
1243                              DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1244   PyModule_AddStringConstant(module, "DS_TYPE_DERIVE",
1245                              DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1246   PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE",
1247                              DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1248   return 0;
1249 }
1250
1251 static int cpy_config(oconfig_item_t *ci) {
1252   PyObject *tb;
1253   int status = 0;
1254
1255   /* Ok in theory we shouldn't do initialization at this point
1256    * but we have to. In order to give python scripts a chance
1257    * to register a config callback we need to be able to execute
1258    * python code during the config callback so we have to start
1259    * the interpreter here. */
1260   /* Do *not* use the python "thread" module at this point! */
1261
1262   if (!Py_IsInitialized() && cpy_init_python())
1263     return 1;
1264
1265   for (int i = 0; i < ci->children_num; ++i) {
1266     oconfig_item_t *item = ci->children + i;
1267
1268     if (strcasecmp(item->key, "Interactive") == 0) {
1269       if (cf_util_get_boolean(item, &do_interactive) != 0) {
1270         status = 1;
1271         continue;
1272       }
1273     } else if (strcasecmp(item->key, "Encoding") == 0) {
1274       char *encoding = NULL;
1275       if (cf_util_get_string(item, &encoding) != 0) {
1276         status = 1;
1277         continue;
1278       }
1279 #ifdef IS_PY3K
1280       ERROR("python: \"Encoding\" was used in the config file but Python3 was "
1281             "used, which does not support changing encodings");
1282       status = 1;
1283       sfree(encoding);
1284       continue;
1285 #else
1286       /* Why is this even necessary? And undocumented? */
1287       if (PyUnicode_SetDefaultEncoding(encoding)) {
1288         cpy_log_exception("setting default encoding");
1289         status = 1;
1290       }
1291 #endif
1292       sfree(encoding);
1293     } else if (strcasecmp(item->key, "LogTraces") == 0) {
1294       _Bool log_traces;
1295       if (cf_util_get_boolean(item, &log_traces) != 0) {
1296         status = 1;
1297         continue;
1298       }
1299       if (!log_traces) {
1300         Py_XDECREF(cpy_format_exception);
1301         cpy_format_exception = NULL;
1302         continue;
1303       }
1304       if (cpy_format_exception)
1305         continue;
1306       tb = PyImport_ImportModule("traceback"); /* New reference. */
1307       if (tb == NULL) {
1308         cpy_log_exception("python initialization");
1309         status = 1;
1310         continue;
1311       }
1312       cpy_format_exception =
1313           PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1314       Py_DECREF(tb);
1315       if (cpy_format_exception == NULL) {
1316         cpy_log_exception("python initialization");
1317         status = 1;
1318       }
1319     } else if (strcasecmp(item->key, "ModulePath") == 0) {
1320       char *dir = NULL;
1321       PyObject *dir_object;
1322
1323       if (cf_util_get_string(item, &dir) != 0) {
1324         status = 1;
1325         continue;
1326       }
1327       dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1328       if (dir_object == NULL) {
1329         ERROR("python plugin: Unable to convert \"%s\" to "
1330               "a python object.",
1331               dir);
1332         free(dir);
1333         cpy_log_exception("python initialization");
1334         status = 1;
1335         continue;
1336       }
1337       if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1338         ERROR("python plugin: Unable to prepend \"%s\" to "
1339               "python module path.",
1340               dir);
1341         cpy_log_exception("python initialization");
1342         status = 1;
1343       }
1344       Py_DECREF(dir_object);
1345       free(dir);
1346     } else if (strcasecmp(item->key, "Import") == 0) {
1347       char *module_name = NULL;
1348       PyObject *module;
1349
1350       if (cf_util_get_string(item, &module_name) != 0) {
1351         status = 1;
1352         continue;
1353       }
1354       module = PyImport_ImportModule(module_name); /* New reference. */
1355       if (module == NULL) {
1356         ERROR("python plugin: Error importing module \"%s\".", module_name);
1357         cpy_log_exception("importing module");
1358         status = 1;
1359       }
1360       free(module_name);
1361       Py_XDECREF(module);
1362     } else if (strcasecmp(item->key, "Module") == 0) {
1363       char *name = NULL;
1364       cpy_callback_t *c;
1365       PyObject *ret;
1366
1367       if (cf_util_get_string(item, &name) != 0) {
1368         status = 1;
1369         continue;
1370       }
1371       for (c = cpy_config_callbacks; c; c = c->next) {
1372         if (strcasecmp(c->name + 7, name) == 0)
1373           break;
1374       }
1375       if (c == NULL) {
1376         WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1377                 "but the plugin isn't loaded or didn't register "
1378                 "a configuration callback.",
1379                 name);
1380         free(name);
1381         continue;
1382       }
1383       free(name);
1384       if (c->data == NULL)
1385         ret = PyObject_CallFunction(
1386             c->callback, "N",
1387             cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1388       else
1389         ret = PyObject_CallFunction(c->callback, "NO",
1390                                     cpy_oconfig_to_pyconfig(item, NULL),
1391                                     c->data); /* New reference. */
1392       if (ret == NULL) {
1393         cpy_log_exception("loading module");
1394         status = 1;
1395       } else
1396         Py_DECREF(ret);
1397     } else {
1398       ERROR("python plugin: Unknown config key \"%s\".", item->key);
1399       status = 1;
1400     }
1401   }
1402   return status;
1403 }
1404
1405 void module_register(void) {
1406   plugin_register_complex_config("python", cpy_config);
1407   plugin_register_init("python", cpy_init);
1408   plugin_register_shutdown("python", cpy_shutdown);
1409 }