1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
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.
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.
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/>.
22 #define PY_SSIZE_T_CLEAN
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wredundant-decls"
26 #pragma GCC diagnostic pop
30 #include <sys/socket.h>
32 #include <systemd/sd-daemon.h>
35 PyDoc_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."
43 PyDoc_STRVAR(booted__doc__,
44 "booted() -> bool\n\n"
45 "Return True iff this system is running under systemd.\n"
46 "Wraps sd_daemon_booted(3)."
49 static PyObject* booted(PyObject *self, PyObject *args) {
54 if (set_error(r, NULL, NULL) < 0)
57 return PyBool_FromLong(r);
60 PyDoc_STRVAR(notify__doc__,
61 "notify(status, unset_environment=False) -> bool\n\n"
62 "Send a message to the init system about a status change.\n"
63 "Wraps sd_notify(3).");
65 static PyObject* notify(PyObject *self, PyObject *args, PyObject *keywds) {
70 static const char* const kwlist[] = {
75 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
76 if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|p:notify",
77 (char**) kwlist, &msg, &unset))
81 if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|O:notify",
82 (char**) kwlist, &msg, &obj))
85 unset = PyObject_IsTrue(obj);
90 r = sd_notify(unset, msg);
91 if (set_error(r, NULL, NULL) < 0)
94 return PyBool_FromLong(r);
98 PyDoc_STRVAR(listen_fds__doc__,
99 "_listen_fds(unset_environment=True) -> int\n\n"
100 "Return the number of descriptors passed to this process by the init system\n"
101 "as part of the socket-based activation logic.\n"
102 "Wraps sd_listen_fds(3)."
105 static PyObject* listen_fds(PyObject *self, PyObject *args, PyObject *keywds) {
109 static const char* const kwlist[] = {"unset_environment", NULL};
110 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
111 if (!PyArg_ParseTupleAndKeywords(args, keywds, "|p:_listen_fds",
112 (char**) kwlist, &unset))
115 PyObject *obj = NULL;
116 if (!PyArg_ParseTupleAndKeywords(args, keywds, "|O:_listen_fds",
117 (char**) kwlist, &obj))
120 unset = PyObject_IsTrue(obj);
125 r = sd_listen_fds(unset);
126 if (set_error(r, NULL, NULL) < 0)
129 return long_FromLong(r);
132 PyDoc_STRVAR(is_fifo__doc__,
133 "_is_fifo(fd, path) -> bool\n\n"
134 "Returns True iff the descriptor refers to a FIFO or a pipe.\n"
135 "Wraps sd_is_fifo(3)."
139 static PyObject* is_fifo(PyObject *self, PyObject *args) {
142 const char *path = NULL;
144 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
145 if (!PyArg_ParseTuple(args, "i|O&:_is_fifo",
146 &fd, Unicode_FSConverter, &path))
149 if (!PyArg_ParseTuple(args, "i|z:_is_fifo", &fd, &path))
153 r = sd_is_fifo(fd, path);
154 if (set_error(r, path, NULL) < 0)
157 return PyBool_FromLong(r);
161 PyDoc_STRVAR(is_mq__doc__,
162 "_is_mq(fd, path) -> bool\n\n"
163 "Returns True iff the descriptor refers to a POSIX message queue.\n"
167 static PyObject* is_mq(PyObject *self, PyObject *args) {
170 const char *path = NULL;
172 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
173 if (!PyArg_ParseTuple(args, "i|O&:_is_mq",
174 &fd, Unicode_FSConverter, &path))
177 if (!PyArg_ParseTuple(args, "i|z:_is_mq", &fd, &path))
181 r = sd_is_mq(fd, path);
182 if (set_error(r, path, NULL) < 0)
185 return PyBool_FromLong(r);
190 PyDoc_STRVAR(is_socket__doc__,
191 "_is_socket(fd, family=AF_UNSPEC, type=0, listening=-1) -> bool\n\n"
192 "Returns True iff the descriptor refers to a socket.\n"
193 "Wraps sd_is_socket(3).\n\n"
194 "Constants for `family` are defined in the socket module."
197 static PyObject* is_socket(PyObject *self, PyObject *args) {
199 int fd, family = AF_UNSPEC, type = 0, listening = -1;
201 if (!PyArg_ParseTuple(args, "i|iii:_is_socket",
202 &fd, &family, &type, &listening))
205 r = sd_is_socket(fd, family, type, listening);
206 if (set_error(r, NULL, NULL) < 0)
209 return PyBool_FromLong(r);
213 PyDoc_STRVAR(is_socket_inet__doc__,
214 "_is_socket_inet(fd, family=AF_UNSPEC, type=0, listening=-1, port=0) -> bool\n\n"
215 "Wraps sd_is_socket_inet(3).\n\n"
216 "Constants for `family` are defined in the socket module."
219 static PyObject* is_socket_inet(PyObject *self, PyObject *args) {
221 int fd, family = AF_UNSPEC, type = 0, listening = -1, port = 0;
223 if (!PyArg_ParseTuple(args, "i|iiii:_is_socket_inet",
224 &fd, &family, &type, &listening, &port))
227 if (port < 0 || port > INT16_MAX) {
228 set_error(-EINVAL, NULL, "port must fit into uint16_t");
232 r = sd_is_socket_inet(fd, family, type, listening, (uint16_t) port);
233 if (set_error(r, NULL, NULL) < 0)
236 return PyBool_FromLong(r);
240 PyDoc_STRVAR(is_socket_unix__doc__,
241 "_is_socket_unix(fd, type, listening, path) -> bool\n\n"
242 "Wraps sd_is_socket_unix(3)."
245 static PyObject* is_socket_unix(PyObject *self, PyObject *args) {
247 int fd, type = 0, listening = -1;
249 Py_ssize_t length = 0;
251 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
252 _cleanup_Py_DECREF_ PyObject *_path = NULL;
253 if (!PyArg_ParseTuple(args, "i|iiO&:_is_socket_unix",
254 &fd, &type, &listening, Unicode_FSConverter, &_path))
257 assert(PyBytes_Check(_path));
258 if (PyBytes_AsStringAndSize(_path, &path, &length))
262 if (!PyArg_ParseTuple(args, "i|iiz#:_is_socket_unix",
263 &fd, &type, &listening, &path, &length))
267 r = sd_is_socket_unix(fd, type, listening, path, length);
268 if (set_error(r, path, NULL) < 0)
271 return PyBool_FromLong(r);
275 static PyMethodDef methods[] = {
276 { "booted", booted, METH_NOARGS, booted__doc__},
277 { "notify", (PyCFunction) notify, METH_VARARGS | METH_KEYWORDS, notify__doc__},
278 { "_listen_fds", (PyCFunction) listen_fds, METH_VARARGS | METH_KEYWORDS, listen_fds__doc__},
279 { "_is_fifo", is_fifo, METH_VARARGS, is_fifo__doc__},
280 { "_is_mq", is_mq, METH_VARARGS, is_mq__doc__},
281 { "_is_socket", is_socket, METH_VARARGS, is_socket__doc__},
282 { "_is_socket_inet", is_socket_inet, METH_VARARGS, is_socket_inet__doc__},
283 { "_is_socket_unix", is_socket_unix, METH_VARARGS, is_socket_unix__doc__},
284 { NULL, NULL, 0, NULL } /* Sentinel */
287 #pragma GCC diagnostic push
288 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
290 #if PY_MAJOR_VERSION < 3
292 PyMODINIT_FUNC init_daemon(void) {
295 m = Py_InitModule3("_daemon", methods, module__doc__);
299 PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START);
300 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
305 static struct PyModuleDef module = {
306 PyModuleDef_HEAD_INIT,
307 "_daemon", /* name of module */
308 module__doc__, /* module documentation, may be NULL */
309 0, /* size of per-interpreter state of the module */
313 PyMODINIT_FUNC PyInit__daemon(void) {
316 m = PyModule_Create(&module);
320 if (PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START) ||
321 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
331 #pragma GCC diagnostic pop