Merge branch 'collectd-5.7'
[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, args,
788                                        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, "write");
948 }
949
950 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
951   return cpy_unregister_generic_userdata(plugin_unregister_notification, arg,
952                                          "notification");
953 }
954
955 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
956   return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
957 }
958
959 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
960   return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
961 }
962
963 static PyMethodDef cpy_methods[] = {
964     {"debug", cpy_debug, METH_VARARGS, log_doc},
965     {"info", cpy_info, METH_VARARGS, log_doc},
966     {"notice", cpy_notice, METH_VARARGS, log_doc},
967     {"warning", cpy_warning, METH_VARARGS, log_doc},
968     {"error", cpy_error, METH_VARARGS, log_doc},
969     {"get_dataset", (PyCFunction)cpy_get_dataset, METH_VARARGS, get_ds_doc},
970     {"flush", (PyCFunction)cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
971     {"register_log", (PyCFunction)cpy_register_log,
972      METH_VARARGS | METH_KEYWORDS, reg_log_doc},
973     {"register_init", (PyCFunction)cpy_register_init,
974      METH_VARARGS | METH_KEYWORDS, reg_init_doc},
975     {"register_config", (PyCFunction)cpy_register_config,
976      METH_VARARGS | METH_KEYWORDS, reg_config_doc},
977     {"register_read", (PyCFunction)cpy_register_read,
978      METH_VARARGS | METH_KEYWORDS, reg_read_doc},
979     {"register_write", (PyCFunction)cpy_register_write,
980      METH_VARARGS | METH_KEYWORDS, reg_write_doc},
981     {"register_notification", (PyCFunction)cpy_register_notification,
982      METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
983     {"register_flush", (PyCFunction)cpy_register_flush,
984      METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
985     {"register_shutdown", (PyCFunction)cpy_register_shutdown,
986      METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
987     {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
988     {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
989     {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
990     {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
991     {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
992     {"unregister_notification", cpy_unregister_notification, METH_O,
993      unregister_doc},
994     {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
995     {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
996     {0, 0, 0, 0}};
997
998 static int cpy_shutdown(void) {
999   PyObject *ret;
1000
1001   if (!state) {
1002     printf(
1003         "================================================================\n");
1004     printf(
1005         "collectd shutdown while running an interactive session. This will\n");
1006     printf("probably leave your terminal in a mess.\n");
1007     printf("Run the command \"reset\" to get it back into a usable state.\n");
1008     printf("You can press Ctrl+D in the interactive session to\n");
1009     printf("close collectd and avoid this problem in the future.\n");
1010     printf(
1011         "================================================================\n");
1012   }
1013
1014   CPY_LOCK_THREADS
1015
1016   for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
1017     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1018                                        (void *)0); /* New reference. */
1019     if (ret == NULL)
1020       cpy_log_exception("shutdown callback");
1021     else
1022       Py_DECREF(ret);
1023   }
1024   PyErr_Print();
1025
1026   Py_BEGIN_ALLOW_THREADS cpy_unregister_list(&cpy_config_callbacks);
1027   cpy_unregister_list(&cpy_init_callbacks);
1028   cpy_unregister_list(&cpy_shutdown_callbacks);
1029   cpy_shutdown_triggered = 1;
1030   Py_END_ALLOW_THREADS
1031
1032       if (!cpy_num_callbacks) {
1033     Py_Finalize();
1034     return 0;
1035   }
1036
1037   CPY_RELEASE_THREADS
1038   return 0;
1039 }
1040
1041 static void *cpy_interactive(void *pipefd) {
1042   PyOS_sighandler_t cur_sig;
1043
1044   /* Signal handler in a plugin? Bad stuff, but the best way to
1045    * handle it I guess. In an interactive session people will
1046    * press Ctrl+C at some time, which will generate a SIGINT.
1047    * This will cause collectd to shutdown, thus killing the
1048    * interactive interpreter, and leaving the terminal in a
1049    * mess. Chances are, this isn't what the user wanted to do.
1050    *
1051    * So this is the plan:
1052    * 1. Restore Python's own signal handler
1053    * 2. Tell Python we just forked so it will accept this thread
1054    *    as the main one. No version of Python will ever handle
1055    *    interrupts anywhere but in the main thread.
1056    * 3. After the interactive loop is done, restore collectd's
1057    *    SIGINT handler.
1058    * 4. Raise SIGINT for a clean shutdown. The signal is sent to
1059    *    the main thread to ensure it wakes up the main interval
1060    *    sleep so that collectd shuts down immediately not in 10
1061    *    seconds.
1062    *
1063    * This will make sure that SIGINT won't kill collectd but
1064    * still interrupt syscalls like sleep and pause. */
1065
1066   if (PyImport_ImportModule("readline") == NULL) {
1067     /* This interactive session will suck. */
1068     cpy_log_exception("interactive session init");
1069   }
1070   cur_sig = PyOS_setsig(SIGINT, python_sigint_handler);
1071   PyOS_AfterFork();
1072   PyEval_InitThreads();
1073   close(*(int *)pipefd);
1074   PyRun_InteractiveLoop(stdin, "<stdin>");
1075   PyOS_setsig(SIGINT, cur_sig);
1076   PyErr_Print();
1077   state = PyEval_SaveThread();
1078   NOTICE("python: Interactive interpreter exited, stopping collectd ...");
1079   pthread_kill(main_thread, SIGINT);
1080   return NULL;
1081 }
1082
1083 static int cpy_init(void) {
1084   PyObject *ret;
1085   int pipefd[2];
1086   char buf;
1087   static pthread_t thread;
1088
1089   if (!Py_IsInitialized()) {
1090     WARNING("python: Plugin loaded but not configured.");
1091     plugin_unregister_shutdown("python");
1092     Py_Finalize();
1093     return 0;
1094   }
1095   main_thread = pthread_self();
1096   if (do_interactive) {
1097     if (pipe(pipefd)) {
1098       ERROR("python: Unable to create pipe.");
1099       return 1;
1100     }
1101     if (plugin_thread_create(&thread, NULL, cpy_interactive, pipefd + 1,
1102                              "python interpreter")) {
1103       ERROR("python: Error creating thread for interactive interpreter.");
1104     }
1105     if (read(pipefd[0], &buf, 1))
1106       ;
1107     (void)close(pipefd[0]);
1108   } else {
1109     PyEval_InitThreads();
1110     state = PyEval_SaveThread();
1111   }
1112   CPY_LOCK_THREADS
1113   for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
1114     ret = PyObject_CallFunctionObjArgs(c->callback, c->data,
1115                                        (void *)0); /* New reference. */
1116     if (ret == NULL)
1117       cpy_log_exception("init callback");
1118     else
1119       Py_DECREF(ret);
1120   }
1121   CPY_RELEASE_THREADS
1122
1123   return 0;
1124 }
1125
1126 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
1127   PyObject *item, *values, *children, *tmp;
1128
1129   if (parent == NULL)
1130     parent = Py_None;
1131
1132   values = PyTuple_New(ci->values_num); /* New reference. */
1133   for (int i = 0; i < ci->values_num; ++i) {
1134     if (ci->values[i].type == OCONFIG_TYPE_STRING) {
1135       PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(
1136                                       ci->values[i].value.string));
1137     } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
1138       PyTuple_SET_ITEM(values, i,
1139                        PyFloat_FromDouble(ci->values[i].value.number));
1140     } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
1141       PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
1142     }
1143   }
1144
1145   tmp = cpy_string_to_unicode_or_bytes(ci->key);
1146   item = PyObject_CallFunction((void *)&ConfigType, "NONO", tmp, parent, values,
1147                                Py_None);
1148   if (item == NULL)
1149     return NULL;
1150   children = PyTuple_New(ci->children_num); /* New reference. */
1151   for (int i = 0; i < ci->children_num; ++i) {
1152     PyTuple_SET_ITEM(children, i,
1153                      cpy_oconfig_to_pyconfig(ci->children + i, item));
1154   }
1155   tmp = ((Config *)item)->children;
1156   ((Config *)item)->children = children;
1157   Py_XDECREF(tmp);
1158   return item;
1159 }
1160
1161 #ifdef IS_PY3K
1162 static struct PyModuleDef collectdmodule = {
1163     PyModuleDef_HEAD_INIT, "collectd",  /* name of module */
1164     "The python interface to collectd", /* module documentation, may be NULL */
1165     -1, cpy_methods};
1166
1167 PyMODINIT_FUNC PyInit_collectd(void) {
1168   return PyModule_Create(&collectdmodule);
1169 }
1170 #endif
1171
1172 static int cpy_init_python(void) {
1173   PyOS_sighandler_t cur_sig;
1174   PyObject *sys;
1175   PyObject *module;
1176
1177 #ifdef IS_PY3K
1178   wchar_t *argv = L"";
1179   /* Add a builtin module, before Py_Initialize */
1180   PyImport_AppendInittab("collectd", PyInit_collectd);
1181 #else
1182   char *argv = "";
1183 #endif
1184
1185   /* Chances are the current signal handler is already SIG_DFL, but let's make
1186    * sure. */
1187   cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
1188   Py_Initialize();
1189   python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
1190
1191   PyType_Ready(&ConfigType);
1192   PyType_Ready(&PluginDataType);
1193   ValuesType.tp_base = &PluginDataType;
1194   PyType_Ready(&ValuesType);
1195   NotificationType.tp_base = &PluginDataType;
1196   PyType_Ready(&NotificationType);
1197   SignedType.tp_base = &PyLong_Type;
1198   PyType_Ready(&SignedType);
1199   UnsignedType.tp_base = &PyLong_Type;
1200   PyType_Ready(&UnsignedType);
1201   sys = PyImport_ImportModule("sys"); /* New reference. */
1202   if (sys == NULL) {
1203     cpy_log_exception("python initialization");
1204     return 1;
1205   }
1206   sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1207   Py_DECREF(sys);
1208   if (sys_path == NULL) {
1209     cpy_log_exception("python initialization");
1210     return 1;
1211   }
1212   PySys_SetArgv(1, &argv);
1213   PyList_SetSlice(sys_path, 0, 1, NULL);
1214
1215 #ifdef IS_PY3K
1216   module = PyImport_ImportModule("collectd");
1217 #else
1218   module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1219 #endif
1220   PyModule_AddObject(module, "Config",
1221                      (void *)&ConfigType); /* Steals a reference. */
1222   PyModule_AddObject(module, "Values",
1223                      (void *)&ValuesType); /* Steals a reference. */
1224   PyModule_AddObject(module, "Notification",
1225                      (void *)&NotificationType); /* Steals a reference. */
1226   PyModule_AddObject(module, "Signed",
1227                      (void *)&SignedType); /* Steals a reference. */
1228   PyModule_AddObject(module, "Unsigned",
1229                      (void *)&UnsignedType); /* Steals a reference. */
1230   PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1231   PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1232   PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1233   PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1234   PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1235   PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1236   PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1237   PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1238   PyModule_AddStringConstant(module, "DS_TYPE_COUNTER",
1239                              DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
1240   PyModule_AddStringConstant(module, "DS_TYPE_GAUGE",
1241                              DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
1242   PyModule_AddStringConstant(module, "DS_TYPE_DERIVE",
1243                              DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
1244   PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE",
1245                              DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
1246   return 0;
1247 }
1248
1249 static int cpy_config(oconfig_item_t *ci) {
1250   PyObject *tb;
1251   int status = 0;
1252
1253   /* Ok in theory we shouldn't do initialization at this point
1254    * but we have to. In order to give python scripts a chance
1255    * to register a config callback we need to be able to execute
1256    * python code during the config callback so we have to start
1257    * the interpreter here. */
1258   /* Do *not* use the python "thread" module at this point! */
1259
1260   if (!Py_IsInitialized() && cpy_init_python())
1261     return 1;
1262
1263   for (int i = 0; i < ci->children_num; ++i) {
1264     oconfig_item_t *item = ci->children + i;
1265
1266     if (strcasecmp(item->key, "Interactive") == 0) {
1267       if (cf_util_get_boolean(item, &do_interactive) != 0) {
1268         status = 1;
1269         continue;
1270       }
1271     } else if (strcasecmp(item->key, "Encoding") == 0) {
1272       char *encoding = NULL;
1273       if (cf_util_get_string(item, &encoding) != 0) {
1274         status = 1;
1275         continue;
1276       }
1277 #ifdef IS_PY3K
1278       ERROR("python: \"Encoding\" was used in the config file but Python3 was "
1279             "used, which does not support changing encodings");
1280       status = 1;
1281       sfree(encoding);
1282       continue;
1283 #else
1284       /* Why is this even necessary? And undocumented? */
1285       if (PyUnicode_SetDefaultEncoding(encoding)) {
1286         cpy_log_exception("setting default encoding");
1287         status = 1;
1288       }
1289 #endif
1290       sfree(encoding);
1291     } else if (strcasecmp(item->key, "LogTraces") == 0) {
1292       _Bool log_traces;
1293       if (cf_util_get_boolean(item, &log_traces) != 0) {
1294         status = 1;
1295         continue;
1296       }
1297       if (!log_traces) {
1298         Py_XDECREF(cpy_format_exception);
1299         cpy_format_exception = NULL;
1300         continue;
1301       }
1302       if (cpy_format_exception)
1303         continue;
1304       tb = PyImport_ImportModule("traceback"); /* New reference. */
1305       if (tb == NULL) {
1306         cpy_log_exception("python initialization");
1307         status = 1;
1308         continue;
1309       }
1310       cpy_format_exception =
1311           PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1312       Py_DECREF(tb);
1313       if (cpy_format_exception == NULL) {
1314         cpy_log_exception("python initialization");
1315         status = 1;
1316       }
1317     } else if (strcasecmp(item->key, "ModulePath") == 0) {
1318       char *dir = NULL;
1319       PyObject *dir_object;
1320
1321       if (cf_util_get_string(item, &dir) != 0) {
1322         status = 1;
1323         continue;
1324       }
1325       dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1326       if (dir_object == NULL) {
1327         ERROR("python plugin: Unable to convert \"%s\" to "
1328               "a python object.",
1329               dir);
1330         free(dir);
1331         cpy_log_exception("python initialization");
1332         status = 1;
1333         continue;
1334       }
1335       if (PyList_Insert(sys_path, 0, dir_object) != 0) {
1336         ERROR("python plugin: Unable to prepend \"%s\" to "
1337               "python module path.",
1338               dir);
1339         cpy_log_exception("python initialization");
1340         status = 1;
1341       }
1342       Py_DECREF(dir_object);
1343       free(dir);
1344     } else if (strcasecmp(item->key, "Import") == 0) {
1345       char *module_name = NULL;
1346       PyObject *module;
1347
1348       if (cf_util_get_string(item, &module_name) != 0) {
1349         status = 1;
1350         continue;
1351       }
1352       module = PyImport_ImportModule(module_name); /* New reference. */
1353       if (module == NULL) {
1354         ERROR("python plugin: Error importing module \"%s\".", module_name);
1355         cpy_log_exception("importing module");
1356         status = 1;
1357       }
1358       free(module_name);
1359       Py_XDECREF(module);
1360     } else if (strcasecmp(item->key, "Module") == 0) {
1361       char *name = NULL;
1362       cpy_callback_t *c;
1363       PyObject *ret;
1364
1365       if (cf_util_get_string(item, &name) != 0) {
1366         status = 1;
1367         continue;
1368       }
1369       for (c = cpy_config_callbacks; c; c = c->next) {
1370         if (strcasecmp(c->name + 7, name) == 0)
1371           break;
1372       }
1373       if (c == NULL) {
1374         WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1375                 "but the plugin isn't loaded or didn't register "
1376                 "a configuration callback.",
1377                 name);
1378         free(name);
1379         continue;
1380       }
1381       free(name);
1382       if (c->data == NULL)
1383         ret = PyObject_CallFunction(
1384             c->callback, "N",
1385             cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1386       else
1387         ret = PyObject_CallFunction(c->callback, "NO",
1388                                     cpy_oconfig_to_pyconfig(item, NULL),
1389                                     c->data); /* New reference. */
1390       if (ret == NULL) {
1391         cpy_log_exception("loading module");
1392         status = 1;
1393       } else
1394         Py_DECREF(ret);
1395     } else {
1396       ERROR("python plugin: Unknown config key \"%s\".", item->key);
1397       status = 1;
1398     }
1399   }
1400   return (status);
1401 }
1402
1403 void module_register(void) {
1404   plugin_register_complex_config("python", cpy_config);
1405   plugin_register_init("python", cpy_init);
1406   plugin_register_shutdown("python", cpy_shutdown);
1407 }