]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/python-systemd/_daemon.c
systemd-python: wrap sd_notify
[thirdparty/systemd.git] / src / python-systemd / _daemon.c
CommitLineData
b04c8c83
ZJS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#define PY_SSIZE_T_CLEAN
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wredundant-decls"
25#include <Python.h>
26#pragma GCC diagnostic pop
27
28#include <stdbool.h>
29#include <assert.h>
30#include <sys/socket.h>
31
32#include <systemd/sd-daemon.h>
33#include "pyutil.h"
34
35PyDoc_STRVAR(module__doc__,
36 "Python interface to the libsystemd-daemon library.\n\n"
37 "Provides _listen_fds, notify, booted, and is_* functions\n"
38 "which wrap sd_listen_fds, sd_notify, sd_booted, sd_is_* and\n"
39 "useful for socket activation and checking if the system is\n"
40 "running under systemd."
41);
42
b04c8c83
ZJS
43
44#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
45static int Unicode_FSConverter(PyObject* obj, void *_result) {
46 PyObject **result = _result;
47
48 assert(result);
49
50 if (!obj)
51 /* cleanup: we don't return Py_CLEANUP_SUPPORTED, so
52 * we can assume that it was PyUnicode_FSConverter. */
53 return PyUnicode_FSConverter(obj, result);
54
55 if (obj == Py_None) {
56 *result = NULL;
57 return 1;
58 }
59
60 return PyUnicode_FSConverter(obj, result);
61}
62#endif
63
64
65PyDoc_STRVAR(booted__doc__,
66 "booted() -> bool\n\n"
67 "Return True iff this system is running under systemd.\n"
68 "Wraps sd_daemon_booted(3)."
69);
70
71static PyObject* booted(PyObject *self, PyObject *args) {
72 int r;
73 assert(args == NULL);
74
75 r = sd_booted();
7ecec470
ZJS
76 if (set_error(r, NULL, NULL))
77 return NULL;
b04c8c83
ZJS
78
79 return PyBool_FromLong(r);
80}
81
925d98b3
ZJS
82PyDoc_STRVAR(notify__doc__,
83 "notify(status, unset_environment=False) -> bool\n\n"
84 "Send a message to the init system about a status change.\n"
85 "Wraps sd_notify(3).");
86
87static PyObject* notify(PyObject *self, PyObject *args, PyObject *keywds) {
88 int r;
89 const char* msg;
90 int unset = false;
91
92 static const char* const kwlist[] = {
93 "status",
94 "unset_environment",
95 NULL,
96 };
97#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
98 if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|p:notify",
99 (char**) kwlist, &msg, &unset))
100 return NULL;
101#else
102 PyObject *obj = NULL;
103 if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|O:notify",
104 (char**) kwlist, &msg, &obj))
105 return NULL;
106 if (obj != NULL)
107 unset = PyObject_IsTrue(obj);
108 if (unset < 0)
109 return NULL;
110#endif
111
112 r = sd_notify(unset, msg);
113 if (set_error(r, NULL, NULL))
114 return NULL;
115
116 return PyBool_FromLong(r);
117}
118
b04c8c83
ZJS
119
120PyDoc_STRVAR(listen_fds__doc__,
121 "_listen_fds(unset_environment=True) -> int\n\n"
122 "Return the number of descriptors passed to this process by the init system\n"
123 "as part of the socket-based activation logic.\n"
124 "Wraps sd_listen_fds(3)."
125);
126
925d98b3 127static PyObject* listen_fds(PyObject *self, PyObject *args, PyObject *keywds) {
b04c8c83
ZJS
128 int r;
129 int unset = true;
130
925d98b3 131 static const char* const kwlist[] = {"unset_environment", NULL};
b04c8c83 132#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
925d98b3
ZJS
133 if (!PyArg_ParseTupleAndKeywords(args, keywds, "|p:_listen_fds",
134 (char**) kwlist, &unset))
b04c8c83
ZJS
135 return NULL;
136#else
137 PyObject *obj = NULL;
925d98b3
ZJS
138 if (!PyArg_ParseTupleAndKeywords(args, keywds, "|O:_listen_fds",
139 (char**) kwlist, &unset, &obj))
b04c8c83
ZJS
140 return NULL;
141 if (obj != NULL)
142 unset = PyObject_IsTrue(obj);
143 if (unset < 0)
144 return NULL;
145#endif
146
147 r = sd_listen_fds(unset);
7ecec470
ZJS
148 if (set_error(r, NULL, NULL))
149 return NULL;
b04c8c83
ZJS
150
151 return long_FromLong(r);
152}
153
154PyDoc_STRVAR(is_fifo__doc__,
155 "_is_fifo(fd, path) -> bool\n\n"
156 "Returns True iff the descriptor refers to a FIFO or a pipe.\n"
157 "Wraps sd_is_fifo(3)."
158);
159
160
161static PyObject* is_fifo(PyObject *self, PyObject *args) {
162 int r;
163 int fd;
164 const char *path = NULL;
165
166#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
167 if (!PyArg_ParseTuple(args, "i|O&:_is_fifo",
168 &fd, Unicode_FSConverter, &path))
169 return NULL;
170#else
171 if (!PyArg_ParseTuple(args, "i|z:_is_fifo", &fd, &path))
172 return NULL;
173#endif
174
175 r = sd_is_fifo(fd, path);
7ecec470
ZJS
176 if (set_error(r, path, NULL))
177 return NULL;
b04c8c83
ZJS
178
179 return PyBool_FromLong(r);
180}
181
182
183PyDoc_STRVAR(is_mq__doc__,
184 "_is_mq(fd, path) -> bool\n\n"
185 "Returns True iff the descriptor refers to a POSIX message queue.\n"
186 "Wraps sd_is_mq(3)."
187);
188
189static PyObject* is_mq(PyObject *self, PyObject *args) {
190 int r;
191 int fd;
192 const char *path = NULL;
193
194#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
195 if (!PyArg_ParseTuple(args, "i|O&:_is_mq",
196 &fd, Unicode_FSConverter, &path))
197 return NULL;
198#else
199 if (!PyArg_ParseTuple(args, "i|z:_is_mq", &fd, &path))
200 return NULL;
201#endif
202
203 r = sd_is_mq(fd, path);
7ecec470
ZJS
204 if (set_error(r, path, NULL))
205 return NULL;
b04c8c83
ZJS
206
207 return PyBool_FromLong(r);
208}
209
210
211
212PyDoc_STRVAR(is_socket__doc__,
213 "_is_socket(fd, family=AF_UNSPEC, type=0, listening=-1) -> bool\n\n"
214 "Returns True iff the descriptor refers to a socket.\n"
215 "Wraps sd_is_socket(3).\n\n"
216 "Constants for `family` are defined in the socket module."
217);
218
219static PyObject* is_socket(PyObject *self, PyObject *args) {
220 int r;
221 int fd, family = AF_UNSPEC, type = 0, listening = -1;
222
223 if (!PyArg_ParseTuple(args, "i|iii:_is_socket",
224 &fd, &family, &type, &listening))
225 return NULL;
226
227 r = sd_is_socket(fd, family, type, listening);
7ecec470
ZJS
228 if (set_error(r, NULL, NULL))
229 return NULL;
b04c8c83
ZJS
230
231 return PyBool_FromLong(r);
232}
233
234
235PyDoc_STRVAR(is_socket_inet__doc__,
236 "_is_socket_inet(fd, family=AF_UNSPEC, type=0, listening=-1, port=0) -> bool\n\n"
237 "Wraps sd_is_socket_inet(3).\n\n"
238 "Constants for `family` are defined in the socket module."
239);
240
241static PyObject* is_socket_inet(PyObject *self, PyObject *args) {
242 int r;
243 int fd, family = AF_UNSPEC, type = 0, listening = -1, port = 0;
244
245 if (!PyArg_ParseTuple(args, "i|iiii:_is_socket_inet",
246 &fd, &family, &type, &listening, &port))
247 return NULL;
248
7ecec470
ZJS
249 if (port < 0 || port > INT16_MAX) {
250 set_error(-EINVAL, NULL, "port must fit into uint16_t");
251 return NULL;
252 }
b04c8c83
ZJS
253
254 r = sd_is_socket_inet(fd, family, type, listening, (uint16_t) port);
7ecec470
ZJS
255 if (set_error(r, NULL, NULL))
256 return NULL;
b04c8c83
ZJS
257
258 return PyBool_FromLong(r);
259}
260
261
262PyDoc_STRVAR(is_socket_unix__doc__,
263 "_is_socket_unix(fd, type, listening, path) -> bool\n\n"
264 "Wraps sd_is_socket_unix(3)."
265);
266
267static PyObject* is_socket_unix(PyObject *self, PyObject *args) {
268 int r;
269 int fd, type = 0, listening = -1;
270 char* path = NULL;
271 Py_ssize_t length = 0;
272
273#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
7fd1b19b 274 _cleanup_Py_DECREF_ PyObject *_path = NULL;
b04c8c83
ZJS
275 if (!PyArg_ParseTuple(args, "i|iiO&:_is_socket_unix",
276 &fd, &type, &listening, Unicode_FSConverter, &_path))
277 return NULL;
278 if (_path) {
279 assert(PyBytes_Check(_path));
280 if (PyBytes_AsStringAndSize(_path, &path, &length))
281 return NULL;
282 }
283#else
284 if (!PyArg_ParseTuple(args, "i|iiz#:_is_socket_unix",
285 &fd, &type, &listening, &path, &length))
286 return NULL;
287#endif
288
289 r = sd_is_socket_unix(fd, type, listening, path, length);
7ecec470
ZJS
290 if (set_error(r, path, NULL))
291 return NULL;
b04c8c83
ZJS
292
293 return PyBool_FromLong(r);
294}
295
296
297static PyMethodDef methods[] = {
298 { "booted", booted, METH_NOARGS, booted__doc__},
925d98b3
ZJS
299 { "notify", (PyCFunction) notify, METH_VARARGS | METH_KEYWORDS, notify__doc__},
300 { "_listen_fds", (PyCFunction) listen_fds, METH_VARARGS | METH_KEYWORDS, listen_fds__doc__},
b04c8c83
ZJS
301 { "_is_fifo", is_fifo, METH_VARARGS, is_fifo__doc__},
302 { "_is_mq", is_mq, METH_VARARGS, is_mq__doc__},
303 { "_is_socket", is_socket, METH_VARARGS, is_socket__doc__},
304 { "_is_socket_inet", is_socket_inet, METH_VARARGS, is_socket_inet__doc__},
305 { "_is_socket_unix", is_socket_unix, METH_VARARGS, is_socket_unix__doc__},
306 { NULL, NULL, 0, NULL } /* Sentinel */
307};
308
309#pragma GCC diagnostic push
310#pragma GCC diagnostic ignored "-Wmissing-prototypes"
311
312#if PY_MAJOR_VERSION < 3
313
314PyMODINIT_FUNC init_daemon(void) {
315 PyObject *m;
316
317 m = Py_InitModule3("_daemon", methods, module__doc__);
318 if (m == NULL)
319 return;
320
321 PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START);
5afbe712 322 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
b04c8c83
ZJS
323}
324
325#else
326
327static struct PyModuleDef module = {
328 PyModuleDef_HEAD_INIT,
329 "_daemon", /* name of module */
330 module__doc__, /* module documentation, may be NULL */
331 0, /* size of per-interpreter state of the module */
332 methods
333};
334
335PyMODINIT_FUNC PyInit__daemon(void) {
336 PyObject *m;
337
338 m = PyModule_Create(&module);
339 if (m == NULL)
340 return NULL;
341
5afbe712
ZJS
342 if (PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START) ||
343 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
b04c8c83
ZJS
344 Py_DECREF(m);
345 return NULL;
346 }
347
348 return m;
349}
350
351#endif
352
353#pragma GCC diagnostic pop