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."
44 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
45 static int Unicode_FSConverter(PyObject* obj, void *_result) {
46 PyObject **result = _result;
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);
60 return PyUnicode_FSConverter(obj, result);
65 PyDoc_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)."
71 static PyObject* booted(PyObject *self, PyObject *args) {
76 if (set_error(r, NULL, NULL))
79 return PyBool_FromLong(r);
83 PyDoc_STRVAR(listen_fds__doc__,
84 "_listen_fds(unset_environment=True) -> int\n\n"
85 "Return the number of descriptors passed to this process by the init system\n"
86 "as part of the socket-based activation logic.\n"
87 "Wraps sd_listen_fds(3)."
90 static PyObject* listen_fds(PyObject *self, PyObject *args) {
94 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
95 if (!PyArg_ParseTuple(args, "|p:_listen_fds", &unset))
99 if (!PyArg_ParseTuple(args, "|O:_listen_fds", &obj))
102 unset = PyObject_IsTrue(obj);
107 r = sd_listen_fds(unset);
108 if (set_error(r, NULL, NULL))
111 return long_FromLong(r);
114 PyDoc_STRVAR(is_fifo__doc__,
115 "_is_fifo(fd, path) -> bool\n\n"
116 "Returns True iff the descriptor refers to a FIFO or a pipe.\n"
117 "Wraps sd_is_fifo(3)."
121 static PyObject* is_fifo(PyObject *self, PyObject *args) {
124 const char *path = NULL;
126 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
127 if (!PyArg_ParseTuple(args, "i|O&:_is_fifo",
128 &fd, Unicode_FSConverter, &path))
131 if (!PyArg_ParseTuple(args, "i|z:_is_fifo", &fd, &path))
135 r = sd_is_fifo(fd, path);
136 if (set_error(r, path, NULL))
139 return PyBool_FromLong(r);
143 PyDoc_STRVAR(is_mq__doc__,
144 "_is_mq(fd, path) -> bool\n\n"
145 "Returns True iff the descriptor refers to a POSIX message queue.\n"
149 static PyObject* is_mq(PyObject *self, PyObject *args) {
152 const char *path = NULL;
154 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
155 if (!PyArg_ParseTuple(args, "i|O&:_is_mq",
156 &fd, Unicode_FSConverter, &path))
159 if (!PyArg_ParseTuple(args, "i|z:_is_mq", &fd, &path))
163 r = sd_is_mq(fd, path);
164 if (set_error(r, path, NULL))
167 return PyBool_FromLong(r);
172 PyDoc_STRVAR(is_socket__doc__,
173 "_is_socket(fd, family=AF_UNSPEC, type=0, listening=-1) -> bool\n\n"
174 "Returns True iff the descriptor refers to a socket.\n"
175 "Wraps sd_is_socket(3).\n\n"
176 "Constants for `family` are defined in the socket module."
179 static PyObject* is_socket(PyObject *self, PyObject *args) {
181 int fd, family = AF_UNSPEC, type = 0, listening = -1;
183 if (!PyArg_ParseTuple(args, "i|iii:_is_socket",
184 &fd, &family, &type, &listening))
187 r = sd_is_socket(fd, family, type, listening);
188 if (set_error(r, NULL, NULL))
191 return PyBool_FromLong(r);
195 PyDoc_STRVAR(is_socket_inet__doc__,
196 "_is_socket_inet(fd, family=AF_UNSPEC, type=0, listening=-1, port=0) -> bool\n\n"
197 "Wraps sd_is_socket_inet(3).\n\n"
198 "Constants for `family` are defined in the socket module."
201 static PyObject* is_socket_inet(PyObject *self, PyObject *args) {
203 int fd, family = AF_UNSPEC, type = 0, listening = -1, port = 0;
205 if (!PyArg_ParseTuple(args, "i|iiii:_is_socket_inet",
206 &fd, &family, &type, &listening, &port))
209 if (port < 0 || port > INT16_MAX) {
210 set_error(-EINVAL, NULL, "port must fit into uint16_t");
214 r = sd_is_socket_inet(fd, family, type, listening, (uint16_t) port);
215 if (set_error(r, NULL, NULL))
218 return PyBool_FromLong(r);
222 PyDoc_STRVAR(is_socket_unix__doc__,
223 "_is_socket_unix(fd, type, listening, path) -> bool\n\n"
224 "Wraps sd_is_socket_unix(3)."
227 static PyObject* is_socket_unix(PyObject *self, PyObject *args) {
229 int fd, type = 0, listening = -1;
231 Py_ssize_t length = 0;
233 #if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
234 _cleanup_Py_DECREF_ PyObject *_path = NULL;
235 if (!PyArg_ParseTuple(args, "i|iiO&:_is_socket_unix",
236 &fd, &type, &listening, Unicode_FSConverter, &_path))
239 assert(PyBytes_Check(_path));
240 if (PyBytes_AsStringAndSize(_path, &path, &length))
244 if (!PyArg_ParseTuple(args, "i|iiz#:_is_socket_unix",
245 &fd, &type, &listening, &path, &length))
249 r = sd_is_socket_unix(fd, type, listening, path, length);
250 if (set_error(r, path, NULL))
253 return PyBool_FromLong(r);
257 static PyMethodDef methods[] = {
258 { "booted", booted, METH_NOARGS, booted__doc__},
259 { "_listen_fds", listen_fds, METH_VARARGS, listen_fds__doc__},
260 { "_is_fifo", is_fifo, METH_VARARGS, is_fifo__doc__},
261 { "_is_mq", is_mq, METH_VARARGS, is_mq__doc__},
262 { "_is_socket", is_socket, METH_VARARGS, is_socket__doc__},
263 { "_is_socket_inet", is_socket_inet, METH_VARARGS, is_socket_inet__doc__},
264 { "_is_socket_unix", is_socket_unix, METH_VARARGS, is_socket_unix__doc__},
265 { NULL, NULL, 0, NULL } /* Sentinel */
268 #pragma GCC diagnostic push
269 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
271 #if PY_MAJOR_VERSION < 3
273 PyMODINIT_FUNC init_daemon(void) {
276 m = Py_InitModule3("_daemon", methods, module__doc__);
280 PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START);
281 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
286 static struct PyModuleDef module = {
287 PyModuleDef_HEAD_INIT,
288 "_daemon", /* name of module */
289 module__doc__, /* module documentation, may be NULL */
290 0, /* size of per-interpreter state of the module */
294 PyMODINIT_FUNC PyInit__daemon(void) {
297 m = PyModule_Create(&module);
301 if (PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START) ||
302 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
312 #pragma GCC diagnostic pop