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
28 #include "systemd/sd-login.h"
33 PyDoc_STRVAR(module__doc__,
34 "Python interface to the libsystemd-login library."
37 #define helper(name) \
38 static PyObject* name(PyObject *self, PyObject *args) { \
39 _cleanup_strv_free_ char **list = NULL; \
43 assert(args == NULL); \
45 r = sd_get_##name(&list); \
48 return PyErr_SetFromErrno(PyExc_IOError); \
51 ans = PyList_New(r); \
55 for (r--; r >= 0; r--) { \
56 PyObject *s = unicode_FromString(list[r]); \
62 PyList_SetItem(ans, r, s); \
73 static PyObject* uids(PyObject *self, PyObject *args) {
74 _cleanup_free_ uid_t *list = NULL;
80 r = sd_get_uids(&list);
83 return PyErr_SetFromErrno(PyExc_IOError);
90 for (r--; r >= 0; r--) {
91 PyObject *s = long_FromLong(list[r]);
97 PyList_SetItem(ans, r, s);
103 PyDoc_STRVAR(seats__doc__,
104 "seats() -> list\n\n"
105 "Returns a list of currently available local seats.\n"
106 "Wraps sd_get_seats(3)."
109 PyDoc_STRVAR(sessions__doc__,
110 "sessions() -> list\n\n"
111 "Returns a list of current login sessions.\n"
112 "Wraps sd_get_sessions(3)."
115 PyDoc_STRVAR(machine_names__doc__,
116 "machine_names() -> list\n\n"
117 "Returns a list of currently running virtual machines\n"
118 "and containers on the system.\n"
119 "Wraps sd_get_machine_names(3)."
122 PyDoc_STRVAR(uids__doc__,
124 "Returns a list of uids of users who currently have login sessions.\n"
125 "Wraps sd_get_uids(3)."
128 static PyMethodDef methods[] = {
129 { "seats", seats, METH_NOARGS, seats__doc__},
130 { "sessions", sessions, METH_NOARGS, sessions__doc__},
131 { "machine_names", machine_names, METH_NOARGS, machine_names__doc__},
132 { "uids", uids, METH_NOARGS, uids__doc__},
139 sd_login_monitor *monitor;
141 static PyTypeObject MonitorType;
143 static void Monitor_dealloc(Monitor* self)
145 sd_login_monitor_unref(self->monitor);
146 Py_TYPE(self)->tp_free((PyObject*)self);
149 PyDoc_STRVAR(Monitor__doc__,
150 "Monitor([category]) -> ...\n\n"
151 "Monitor may be used to monitor login sessions, users, seats,\n"
152 "and virtual machines/containers. Monitor provides a file\n"
153 "descriptor which can be integrated in an external event loop.\n"
154 "See man:sd_login_monitor_new(3) for the details about what\n"
155 "can be monitored.");
156 static int Monitor_init(Monitor *self, PyObject *args, PyObject *keywds)
158 const char *category = NULL;
161 static const char* const kwlist[] = {"category", NULL};
162 if (!PyArg_ParseTupleAndKeywords(args, keywds, "|z", (char**) kwlist,
166 Py_BEGIN_ALLOW_THREADS
167 r = sd_login_monitor_new(category, &self->monitor);
170 return set_error(r, NULL, "Invalid category");
174 PyDoc_STRVAR(Monitor_fileno__doc__,
175 "fileno() -> int\n\n"
176 "Get a file descriptor to poll for events.\n"
177 "This method wraps sd_login_monitor_get_fd(3).");
178 static PyObject* Monitor_fileno(Monitor *self, PyObject *args)
180 int fd = sd_login_monitor_get_fd(self->monitor);
181 set_error(fd, NULL, NULL);
184 return long_FromLong(fd);
188 PyDoc_STRVAR(Monitor_get_events__doc__,
189 "get_events() -> int\n\n"
190 "Returns a mask of poll() events to wait for on the file\n"
191 "descriptor returned by .fileno().\n\n"
192 "See man:sd_login_monitor_get_events(3) for further discussion.");
193 static PyObject* Monitor_get_events(Monitor *self, PyObject *args)
195 int r = sd_login_monitor_get_events(self->monitor);
196 set_error(r, NULL, NULL);
199 return long_FromLong(r);
203 PyDoc_STRVAR(Monitor_get_timeout__doc__,
204 "get_timeout() -> int or None\n\n"
205 "Returns a timeout value for usage in poll(), the time since the\n"
206 "epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
208 "The return value must be converted to a relative timeout in\n"
209 "milliseconds if it is to be used as an argument for poll().\n"
210 "See man:sd_login_monitor_get_timeout(3) for further discussion.");
211 static PyObject* Monitor_get_timeout(Monitor *self, PyObject *args)
216 r = sd_login_monitor_get_timeout(self->monitor, &t);
217 set_error(r, NULL, NULL);
221 if (t == (uint64_t) -1)
224 assert_cc(sizeof(unsigned long long) == sizeof(t));
225 return PyLong_FromUnsignedLongLong(t);
229 PyDoc_STRVAR(Monitor_get_timeout_ms__doc__,
230 "get_timeout_ms() -> int\n\n"
231 "Returns a timeout value suitable for usage in poll(), the value\n"
232 "returned by .get_timeout() converted to relative ms, or -1 if\n"
233 "no timeout is necessary.");
234 static PyObject* Monitor_get_timeout_ms(Monitor *self, PyObject *args)
239 r = sd_login_monitor_get_timeout(self->monitor, &t);
240 set_error(r, NULL, NULL);
244 return absolute_timeout(t);
248 PyDoc_STRVAR(Monitor_close__doc__,
249 "close() -> None\n\n"
250 "Free resources allocated by this Monitor object.\n"
251 "This method invokes sd_login_monitor_unref().\n"
252 "See man:sd_login_monitor_unref(3).");
253 static PyObject* Monitor_close(Monitor *self, PyObject *args)
258 sd_login_monitor_unref(self->monitor);
259 self->monitor = NULL;
264 PyDoc_STRVAR(Monitor_flush__doc__,
265 "flush() -> None\n\n"
266 "Reset the wakeup state of the monitor object.\n"
267 "This method invokes sd_login_monitor_flush().\n"
268 "See man:sd_login_monitor_flush(3).");
269 static PyObject* Monitor_flush(Monitor *self, PyObject *args)
274 Py_BEGIN_ALLOW_THREADS
275 sd_login_monitor_flush(self->monitor);
281 PyDoc_STRVAR(Monitor___enter____doc__,
282 "__enter__() -> self\n\n"
283 "Part of the context manager protocol.\n"
285 static PyObject* Monitor___enter__(PyObject *self, PyObject *args)
295 PyDoc_STRVAR(Monitor___exit____doc__,
296 "__exit__(type, value, traceback) -> None\n\n"
297 "Part of the context manager protocol.\n"
298 "Closes the monitor..\n");
299 static PyObject* Monitor___exit__(Monitor *self, PyObject *args)
301 return Monitor_close(self, args);
305 static PyMethodDef Monitor_methods[] = {
306 {"fileno", (PyCFunction) Monitor_fileno, METH_NOARGS, Monitor_fileno__doc__},
307 {"get_events", (PyCFunction) Monitor_get_events, METH_NOARGS, Monitor_get_events__doc__},
308 {"get_timeout", (PyCFunction) Monitor_get_timeout, METH_NOARGS, Monitor_get_timeout__doc__},
309 {"get_timeout_ms", (PyCFunction) Monitor_get_timeout_ms, METH_NOARGS, Monitor_get_timeout_ms__doc__},
310 {"close", (PyCFunction) Monitor_close, METH_NOARGS, Monitor_close__doc__},
311 {"flush", (PyCFunction) Monitor_flush, METH_NOARGS, Monitor_flush__doc__},
312 {"__enter__", (PyCFunction) Monitor___enter__, METH_NOARGS, Monitor___enter____doc__},
313 {"__exit__", (PyCFunction) Monitor___exit__, METH_VARARGS, Monitor___exit____doc__},
317 static PyTypeObject MonitorType = {
318 PyVarObject_HEAD_INIT(NULL, 0)
319 .tp_name = "login.Monitor",
320 .tp_basicsize = sizeof(Monitor),
321 .tp_dealloc = (destructor) Monitor_dealloc,
322 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
323 .tp_doc = Monitor__doc__,
324 .tp_methods = Monitor_methods,
325 .tp_init = (initproc) Monitor_init,
326 .tp_new = PyType_GenericNew,
330 #pragma GCC diagnostic push
331 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
333 #if PY_MAJOR_VERSION < 3
335 PyMODINIT_FUNC initlogin(void) {
338 if (PyType_Ready(&MonitorType) < 0)
341 m = Py_InitModule3("login", methods, module__doc__);
345 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
347 Py_INCREF(&MonitorType);
348 PyModule_AddObject(m, "Monitor", (PyObject *) &MonitorType);
352 static struct PyModuleDef module = {
353 PyModuleDef_HEAD_INIT,
354 "login", /* name of module */
355 module__doc__, /* module documentation, may be NULL */
356 -1, /* size of per-interpreter state of the module */
360 PyMODINIT_FUNC PyInit_login(void) {
363 if (PyType_Ready(&MonitorType) < 0)
366 m = PyModule_Create(&module);
370 if (PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
375 Py_INCREF(&MonitorType);
376 if (PyModule_AddObject(m, "Monitor", (PyObject *) &MonitorType)) {
377 Py_DECREF(&MonitorType);
387 #pragma GCC diagnostic pop