chiark / gitweb /
3e109817076b43612db1a17bc4928e0e9163b9ce
[elogind.git] / src / python-systemd / _journal.c
1 #include <Python.h>
2
3 #define SD_JOURNAL_SUPPRESS_LOCATION
4 #include <systemd/sd-journal.h>
5
6 #include "macro.h"
7
8 PyDoc_STRVAR(journal_sendv__doc__,
9              "sendv('FIELD=value', 'FIELD=value', ...) -> None\n\n"
10              "Send an entry to the journal."
11              );
12
13 static PyObject *
14 journal_sendv(PyObject *self, PyObject *args) {
15     struct iovec *iov = NULL;
16     int argc = PyTuple_Size(args);
17     int i, r;
18     PyObject *ret = NULL;
19
20     PyObject **encoded = calloc(argc, sizeof(PyObject*));
21     if (!encoded) {
22         ret = PyErr_NoMemory();
23         goto out1;
24     }
25
26     // Allocate sufficient iovector space for the arguments.
27     iov = malloc(argc * sizeof(struct iovec));
28     if (!iov) {
29         ret = PyErr_NoMemory();
30         goto out;
31     }
32
33     // Iterate through the Python arguments and fill the iovector.
34     for (i = 0; i < argc; ++i) {
35         PyObject *item = PyTuple_GetItem(args, i);
36         char *stritem;
37         Py_ssize_t length;
38
39         if (PyUnicode_Check(item)) {
40             encoded[i] = PyUnicode_AsEncodedString(item, "utf-8", "strict");
41             if (encoded[i] == NULL)
42                 goto out;
43             item = encoded[i];
44         }
45         if (PyBytes_AsStringAndSize(item, &stritem, &length))
46             goto out;
47
48         iov[i].iov_base = stritem;
49         iov[i].iov_len = length;
50     }
51
52     // Clear errno, because sd_journal_sendv will not set it by
53     // itself, unless an error occurs in one of the system calls.
54     errno = 0;
55
56     // Send the iovector to the journal.
57     r = sd_journal_sendv(iov, argc);
58
59     if (r) {
60         if (errno)
61             PyErr_SetFromErrno(PyExc_IOError);
62         else
63             PyErr_SetString(PyExc_ValueError, "invalid message format");
64         goto out;
65     }
66
67     // End with success.
68     Py_INCREF(Py_None);
69     ret = Py_None;
70
71 out:
72     for (i = 0; i < argc; ++i)
73         Py_XDECREF(encoded[i]);
74
75     free(encoded);
76
77 out1:
78     // Free the iovector. The actual strings
79     // are already managed by Python.
80     free(iov);
81
82     return ret;
83 }
84
85 PyDoc_STRVAR(journal_stream_fd__doc__,
86              "stream_fd(identifier, priority, level_prefix) -> fd\n\n"
87              "Open a stream to journal by calling sd_journal_stream_fd(3)."
88              );
89
90 static PyObject*
91 journal_stream_fd(PyObject *self, PyObject *args) {
92     const char* identifier;
93     int priority, level_prefix;
94     int fd;
95     if (!PyArg_ParseTuple(args, "sii:stream_fd",
96                           &identifier, &priority, &level_prefix))
97         return NULL;
98
99     fd = sd_journal_stream_fd(identifier, priority, level_prefix);
100     if (fd < 0)
101         return PyErr_SetFromErrno(PyExc_IOError);
102
103     return PyLong_FromLong(fd);
104 }
105
106 static PyMethodDef methods[] = {
107     {"sendv",  journal_sendv, METH_VARARGS, journal_sendv__doc__},
108     {"stream_fd", journal_stream_fd, METH_VARARGS,
109      journal_stream_fd__doc__},
110     {NULL, NULL, 0, NULL}        /* Sentinel */
111 };
112
113 #if PY_MAJOR_VERSION < 3
114
115 PyMODINIT_FUNC
116 init_journal(void)
117 {
118     (void) Py_InitModule("_journal", methods);
119 }
120
121 #else
122
123 static struct PyModuleDef module = {
124     PyModuleDef_HEAD_INIT,
125     "_journal", /* name of module */
126     NULL, /* module documentation, may be NULL */
127     0, /* size of per-interpreter state of the module */
128     methods
129 };
130
131 PyMODINIT_FUNC
132 PyInit__journal(void)
133 {
134     return PyModule_Create(&module);
135 }
136
137 #endif