mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Remove python-systemd
python-system has moved to it's own repository: https://github.com/systemd/python-systemd
This commit is contained in:
parent
fc08079ef2
commit
2799e519ca
165
Makefile.am
165
Makefile.am
@ -5620,164 +5620,6 @@ EXTRA_DIST += \
|
||||
test/loopy.service.d \
|
||||
test/loopy.service.d/compat.conf
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
if HAVE_PYTHON_DEVEL
|
||||
pkgpyexec_LTLIBRARIES = \
|
||||
_journal.la \
|
||||
id128.la \
|
||||
_daemon.la \
|
||||
_reader.la \
|
||||
login.la
|
||||
|
||||
_journal_la_SOURCES = \
|
||||
src/python-systemd/_journal.c
|
||||
|
||||
_journal_la_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
-fvisibility=default \
|
||||
$(PYTHON_DEVEL_CFLAGS)
|
||||
|
||||
_journal_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-shared \
|
||||
-module \
|
||||
-avoid-version
|
||||
|
||||
_journal_la_LIBADD = \
|
||||
$(PYTHON_DEVEL_LIBS) \
|
||||
libsystemd.la
|
||||
|
||||
id128_la_SOURCES = \
|
||||
src/python-systemd/id128.c \
|
||||
src/python-systemd/pyutil.c \
|
||||
src/python-systemd/pyutil.h
|
||||
|
||||
nodist_id128_la_SOURCES = \
|
||||
src/python-systemd/id128-constants.h
|
||||
|
||||
id128_la_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
-fvisibility=default \
|
||||
$(PYTHON_DEVEL_CFLAGS) \
|
||||
-I$(top_builddir)/src/python-systemd
|
||||
|
||||
id128_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-shared \
|
||||
-module \
|
||||
-avoid-version
|
||||
|
||||
id128_la_LIBADD = \
|
||||
$(PYTHON_DEVEL_LIBS) \
|
||||
libshared.la \
|
||||
libsystemd.la
|
||||
|
||||
_daemon_la_SOURCES = \
|
||||
src/python-systemd/_daemon.c \
|
||||
src/python-systemd/pyutil.c \
|
||||
src/python-systemd/pyutil.h
|
||||
|
||||
_daemon_la_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
-fvisibility=default \
|
||||
$(PYTHON_DEVEL_CFLAGS) \
|
||||
-I$(top_builddir)/src/python-systemd
|
||||
|
||||
_daemon_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-shared \
|
||||
-module \
|
||||
-avoid-version
|
||||
|
||||
_daemon_la_LIBADD = \
|
||||
$(PYTHON_DEVEL_LIBS) \
|
||||
libshared.la \
|
||||
libsystemd.la
|
||||
|
||||
_reader_la_SOURCES = \
|
||||
src/python-systemd/_reader.c \
|
||||
src/python-systemd/pyutil.c \
|
||||
src/python-systemd/pyutil.h
|
||||
|
||||
_reader_la_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
-fvisibility=default \
|
||||
$(PYTHON_DEVEL_CFLAGS)
|
||||
|
||||
_reader_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-shared \
|
||||
-module \
|
||||
-avoid-version
|
||||
|
||||
_reader_la_LIBADD = \
|
||||
$(PYTHON_DEVEL_LIBS) \
|
||||
libshared.la \
|
||||
libsystemd.la
|
||||
|
||||
login_la_SOURCES = \
|
||||
src/python-systemd/login.c \
|
||||
src/python-systemd/pyutil.c \
|
||||
src/python-systemd/pyutil.h
|
||||
|
||||
login_la_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
-fvisibility=default \
|
||||
$(PYTHON_DEVEL_CFLAGS)
|
||||
|
||||
login_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-shared \
|
||||
-module \
|
||||
-avoid-version
|
||||
|
||||
login_la_LIBADD = \
|
||||
$(PYTHON_DEVEL_LIBS) \
|
||||
libshared.la \
|
||||
libsystemd.la
|
||||
|
||||
dist_pkgpyexec_PYTHON = \
|
||||
src/python-systemd/journal.py \
|
||||
src/python-systemd/daemon.py \
|
||||
src/python-systemd/__init__.py
|
||||
|
||||
src/python-systemd/id128-constants.h: src/systemd/sd-messages.h
|
||||
$(AM_V_at)$(MKDIR_P) $(dir $@)
|
||||
$(AM_V_GEN)$(SED) -n -r 's/,//g; s/#define (SD_MESSAGE_[A-Z0-9_]+)\s.*/add_id(m, "\1", \1) JOINER/p' <$< >$@
|
||||
|
||||
BUILT_SOURCES += \
|
||||
$(nodist_id128_la_SOURCES)
|
||||
|
||||
SPHINXOPTS = -D version=$(VERSION) -D release=$(VERSION)
|
||||
sphinx-%:
|
||||
$(AM_V_at)test -n "$(SPHINX_BUILD)" || { echo " *** sphinx-build is not available"; exit 1; }
|
||||
$(AM_V_GEN)PYTHONPATH=$(DESTDIR)$(pyexecdir) LD_LIBRARY_PATH=$(DESTDIR)$(libdir) $(SPHINX_BUILD) -b $* $(SPHINXOPTS) $(top_srcdir)/src/python-systemd/docs $(top_builddir)/docs/html/python-systemd/
|
||||
$(AM_V_at)echo Output has been generated in $(abs_top_builddir)/docs/html/python-systemd/
|
||||
|
||||
python-shell:
|
||||
$(AM_V_at)echo "Starting python with $(DESTDIR)$(pyexecdir)"
|
||||
$(AM_V_at)PYTHONPATH=$(DESTDIR)$(pyexecdir) LD_LIBRARY_PATH=$(DESTDIR)$(libdir) $(PYTHON)
|
||||
|
||||
destdir-sphinx: all
|
||||
dir="$$(mktemp -d /tmp/systemd-install.XXXXXX)" && \
|
||||
$(MAKE) DESTDIR="$$dir" install && \
|
||||
$(MAKE) DESTDIR="$$dir" sphinx-html && \
|
||||
rm -rf "$$dir"
|
||||
|
||||
endif
|
||||
|
||||
CLEAN_LOCAL_HOOKS += clean-sphinx
|
||||
|
||||
.PHONY: python-shell destdir-sphinx clean-sphinx clean-python
|
||||
|
||||
clean-sphinx:
|
||||
-rm -rf docs/html/python-systemd/
|
||||
|
||||
# Remove Python stuff, e.g. to force rebuilding for a different Python version.
|
||||
clean-python:
|
||||
-rm -rf src/python-systemd/.libs src/python-systemd/*.l[ao]
|
||||
-rm -f _daemon.la id128.la _journal.la login.la _reader.la
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
if ENABLE_COMPAT_LIBS
|
||||
libsystemd-%.c: src/compat-libs/libsystemd-%.sym
|
||||
@ -5950,7 +5792,6 @@ substitutions = \
|
||||
'|RC_LOCAL_SCRIPT_PATH_START=$(RC_LOCAL_SCRIPT_PATH_START)|' \
|
||||
'|RC_LOCAL_SCRIPT_PATH_STOP=$(RC_LOCAL_SCRIPT_PATH_STOP)|' \
|
||||
'|PYTHON=$(PYTHON)|' \
|
||||
'|PYTHON_BINARY=$(PYTHON_BINARY)|' \
|
||||
'|NTP_SERVERS=$(NTP_SERVERS)|' \
|
||||
'|DNS_SERVERS=$(DNS_SERVERS)|' \
|
||||
'|systemuidmax=$(SYSTEM_UID_MAX)|' \
|
||||
@ -6251,11 +6092,6 @@ DISTCHECK_CONFIGURE_FLAGS += \
|
||||
--with-sysvrcnd-path=
|
||||
endif
|
||||
|
||||
if HAVE_PYTHON
|
||||
DISTCHECK_CONFIGURE_FLAGS += \
|
||||
--with-python
|
||||
endif
|
||||
|
||||
if ENABLE_SPLIT_USR
|
||||
DISTCHECK_CONFIGURE_FLAGS += \
|
||||
--enable-split-usr
|
||||
@ -6312,7 +6148,6 @@ www_target = www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd
|
||||
.PHONY: doc-sync
|
||||
doc-sync: all destdir-sphinx
|
||||
rsync -rlv --delete-excluded --include="*.html" --exclude="*" --omit-dir-times man/ $(www_target)/man/
|
||||
rsync -rlv --delete --omit-dir-times docs/html/python-systemd/ $(www_target)/python-systemd/
|
||||
|
||||
.PHONY: gardel
|
||||
gardel: upload
|
||||
|
29
configure.ac
29
configure.ac
@ -238,7 +238,7 @@ AC_CHECK_SIZEOF(rlim_t,,[
|
||||
])
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# we use python to build the man page index, and for systemd-python
|
||||
# we use python to build the man page index
|
||||
have_python=no
|
||||
AC_ARG_WITH([python],
|
||||
[AS_HELP_STRING([--without-python], [Disable building the man page index and systemd-python (default: test)])])
|
||||
@ -260,30 +260,7 @@ AS_IF([test "$have_python" != "yes"], [
|
||||
AS_IF([test "$with_python" != "no"],
|
||||
[AC_MSG_WARN([*** python support not found, some documentation cannot be built])])
|
||||
])
|
||||
|
||||
AM_CONDITIONAL([HAVE_PYTHON], [test "x$have_python" = "xyes"])
|
||||
AS_IF([test "x$PYTHON_BINARY" = "x"],
|
||||
[AS_IF([test "x$have_python" = "xyes"],
|
||||
[PYTHON_BINARY="$(which "$PYTHON")"],
|
||||
[PYTHON_BINARY=/usr/bin/python])])
|
||||
AC_ARG_VAR(PYTHON_BINARY, [Python binary used to launch installed scripts])
|
||||
|
||||
AS_IF([test "x$have_python" != "xyes" -a "x$enable_python_devel" = "xyes"],
|
||||
[AC_MSG_ERROR([*** python-devel support requires --with-python])])
|
||||
|
||||
have_python_devel=no
|
||||
AC_ARG_ENABLE(python_devel, AS_HELP_STRING([--disable-python-devel], [Do not build python modules]))
|
||||
AS_IF([test "x$have_python" = "xyes" -a "x$enable_python_devel" != "xno"], [
|
||||
PKG_CHECK_MODULES([PYTHON_DEVEL], [python-${PYTHON_VERSION}],
|
||||
[have_python_devel=yes],
|
||||
[PKG_CHECK_MODULES([PYTHON_DEVEL], [python],
|
||||
[have_python_devel=yes],
|
||||
[have_python_devel=no])])
|
||||
AS_IF([test "x$have_python_devel" = xno -a "x$enable_python_devel" = xyes],
|
||||
[AC_MSG_ERROR([*** python-devel support requested but libraries not found])])
|
||||
AC_PATH_PROGS(SPHINX_BUILD, sphinx-build-${PYTHON_VERSION} sphinx-build)
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_PYTHON_DEVEL], [test "$have_python_devel" = "yes"])
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
@ -1566,7 +1543,6 @@ AC_MSG_RESULT([
|
||||
terminal: ${have_terminal}
|
||||
kdbus: ${have_kdbus}
|
||||
Python: ${have_python}
|
||||
Python Headers: ${have_python_devel}
|
||||
man pages: ${have_manpages}
|
||||
test coverage: ${have_coverage}
|
||||
Split /usr: ${enable_split_usr}
|
||||
@ -1587,7 +1563,6 @@ AC_MSG_RESULT([
|
||||
SysV init scripts: ${SYSTEM_SYSVINIT_PATH}
|
||||
SysV rc?.d directories: ${SYSTEM_SYSVRCND_PATH}
|
||||
Build Python: ${PYTHON}
|
||||
Installation Python: ${PYTHON_BINARY}
|
||||
sphinx binary: ${SPHINX_BUILD}
|
||||
PAM modules dir: ${with_pamlibdir}
|
||||
PAM configuration dir: ${with_pamconfdir}
|
||||
@ -1608,6 +1583,4 @@ AC_MSG_RESULT([
|
||||
CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
|
||||
CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
|
||||
LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
|
||||
PYTHON_CFLAGS: ${PYTHON_DEVEL_CFLAGS}
|
||||
PYTHON_LIBS: ${PYTHON_DEVEL_LIBS}
|
||||
])
|
||||
|
@ -225,12 +225,6 @@
|
||||
<xsl:text>systemd.directives.html</xsl:text>
|
||||
</xsl:attribute>
|
||||
<xsl:text>Directives </xsl:text>
|
||||
</a>·
|
||||
<a>
|
||||
<xsl:attribute name="href">
|
||||
<xsl:text>../python-systemd/index.html</xsl:text>
|
||||
</xsl:attribute>
|
||||
<xsl:text>Python </xsl:text>
|
||||
</a>
|
||||
|
||||
<span style="float:right">
|
||||
|
2
src/python-systemd/.gitignore
vendored
2
src/python-systemd/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
/id128-constants.h
|
||||
*.py[oc]
|
@ -1 +0,0 @@
|
||||
../Makefile
|
@ -1,18 +0,0 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil -*- */
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# Copyright 2012 David Strauss
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# systemd is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
@ -1,331 +0,0 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
#include <Python.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "systemd/sd-daemon.h"
|
||||
#include "pyutil.h"
|
||||
#include "macro.h"
|
||||
|
||||
PyDoc_STRVAR(module__doc__,
|
||||
"Python interface to the libsystemd-daemon library.\n\n"
|
||||
"Provides _listen_fds, notify, booted, and is_* functions\n"
|
||||
"which wrap sd_listen_fds, sd_notify, sd_booted, sd_is_* and\n"
|
||||
"useful for socket activation and checking if the system is\n"
|
||||
"running under systemd."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(booted__doc__,
|
||||
"booted() -> bool\n\n"
|
||||
"Return True iff this system is running under systemd.\n"
|
||||
"Wraps sd_daemon_booted(3)."
|
||||
);
|
||||
|
||||
static PyObject* booted(PyObject *self, PyObject *args) {
|
||||
int r;
|
||||
assert(args == NULL);
|
||||
|
||||
r = sd_booted();
|
||||
if (set_error(r, NULL, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return PyBool_FromLong(r);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(notify__doc__,
|
||||
"notify(status, unset_environment=False) -> bool\n\n"
|
||||
"Send a message to the init system about a status change.\n"
|
||||
"Wraps sd_notify(3).");
|
||||
|
||||
static PyObject* notify(PyObject *self, PyObject *args, PyObject *keywds) {
|
||||
int r;
|
||||
const char* msg;
|
||||
int unset = false;
|
||||
|
||||
static const char* const kwlist[] = {
|
||||
"status",
|
||||
"unset_environment",
|
||||
NULL,
|
||||
};
|
||||
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|p:notify",
|
||||
(char**) kwlist, &msg, &unset))
|
||||
return NULL;
|
||||
#else
|
||||
PyObject *obj = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|O:notify",
|
||||
(char**) kwlist, &msg, &obj))
|
||||
return NULL;
|
||||
if (obj != NULL)
|
||||
unset = PyObject_IsTrue(obj);
|
||||
if (unset < 0)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
r = sd_notify(unset, msg);
|
||||
if (set_error(r, NULL, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return PyBool_FromLong(r);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(listen_fds__doc__,
|
||||
"_listen_fds(unset_environment=True) -> int\n\n"
|
||||
"Return the number of descriptors passed to this process by the init system\n"
|
||||
"as part of the socket-based activation logic.\n"
|
||||
"Wraps sd_listen_fds(3)."
|
||||
);
|
||||
|
||||
static PyObject* listen_fds(PyObject *self, PyObject *args, PyObject *keywds) {
|
||||
int r;
|
||||
int unset = true;
|
||||
|
||||
static const char* const kwlist[] = {"unset_environment", NULL};
|
||||
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|p:_listen_fds",
|
||||
(char**) kwlist, &unset))
|
||||
return NULL;
|
||||
#else
|
||||
PyObject *obj = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|O:_listen_fds",
|
||||
(char**) kwlist, &obj))
|
||||
return NULL;
|
||||
if (obj != NULL)
|
||||
unset = PyObject_IsTrue(obj);
|
||||
if (unset < 0)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
r = sd_listen_fds(unset);
|
||||
if (set_error(r, NULL, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return long_FromLong(r);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(is_fifo__doc__,
|
||||
"_is_fifo(fd, path) -> bool\n\n"
|
||||
"Returns True iff the descriptor refers to a FIFO or a pipe.\n"
|
||||
"Wraps sd_is_fifo(3)."
|
||||
);
|
||||
|
||||
|
||||
static PyObject* is_fifo(PyObject *self, PyObject *args) {
|
||||
int r;
|
||||
int fd;
|
||||
const char *path = NULL;
|
||||
|
||||
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
|
||||
if (!PyArg_ParseTuple(args, "i|O&:_is_fifo",
|
||||
&fd, Unicode_FSConverter, &path))
|
||||
return NULL;
|
||||
#else
|
||||
if (!PyArg_ParseTuple(args, "i|z:_is_fifo", &fd, &path))
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
r = sd_is_fifo(fd, path);
|
||||
if (set_error(r, path, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return PyBool_FromLong(r);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(is_mq__doc__,
|
||||
"_is_mq(fd, path) -> bool\n\n"
|
||||
"Returns True iff the descriptor refers to a POSIX message queue.\n"
|
||||
"Wraps sd_is_mq(3)."
|
||||
);
|
||||
|
||||
static PyObject* is_mq(PyObject *self, PyObject *args) {
|
||||
int r;
|
||||
int fd;
|
||||
const char *path = NULL;
|
||||
|
||||
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
|
||||
if (!PyArg_ParseTuple(args, "i|O&:_is_mq",
|
||||
&fd, Unicode_FSConverter, &path))
|
||||
return NULL;
|
||||
#else
|
||||
if (!PyArg_ParseTuple(args, "i|z:_is_mq", &fd, &path))
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
r = sd_is_mq(fd, path);
|
||||
if (set_error(r, path, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return PyBool_FromLong(r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyDoc_STRVAR(is_socket__doc__,
|
||||
"_is_socket(fd, family=AF_UNSPEC, type=0, listening=-1) -> bool\n\n"
|
||||
"Returns True iff the descriptor refers to a socket.\n"
|
||||
"Wraps sd_is_socket(3).\n\n"
|
||||
"Constants for `family` are defined in the socket module."
|
||||
);
|
||||
|
||||
static PyObject* is_socket(PyObject *self, PyObject *args) {
|
||||
int r;
|
||||
int fd, family = AF_UNSPEC, type = 0, listening = -1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i|iii:_is_socket",
|
||||
&fd, &family, &type, &listening))
|
||||
return NULL;
|
||||
|
||||
r = sd_is_socket(fd, family, type, listening);
|
||||
if (set_error(r, NULL, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return PyBool_FromLong(r);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(is_socket_inet__doc__,
|
||||
"_is_socket_inet(fd, family=AF_UNSPEC, type=0, listening=-1, port=0) -> bool\n\n"
|
||||
"Wraps sd_is_socket_inet(3).\n\n"
|
||||
"Constants for `family` are defined in the socket module."
|
||||
);
|
||||
|
||||
static PyObject* is_socket_inet(PyObject *self, PyObject *args) {
|
||||
int r;
|
||||
int fd, family = AF_UNSPEC, type = 0, listening = -1, port = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i|iiii:_is_socket_inet",
|
||||
&fd, &family, &type, &listening, &port))
|
||||
return NULL;
|
||||
|
||||
if (port < 0 || port > UINT16_MAX) {
|
||||
set_error(-EINVAL, NULL, "port must fit into uint16_t");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = sd_is_socket_inet(fd, family, type, listening, (uint16_t) port);
|
||||
if (set_error(r, NULL, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return PyBool_FromLong(r);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(is_socket_unix__doc__,
|
||||
"_is_socket_unix(fd, type, listening, path) -> bool\n\n"
|
||||
"Wraps sd_is_socket_unix(3)."
|
||||
);
|
||||
|
||||
static PyObject* is_socket_unix(PyObject *self, PyObject *args) {
|
||||
int r;
|
||||
int fd, type = 0, listening = -1;
|
||||
char* path = NULL;
|
||||
Py_ssize_t length = 0;
|
||||
|
||||
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
|
||||
_cleanup_Py_DECREF_ PyObject *_path = NULL;
|
||||
if (!PyArg_ParseTuple(args, "i|iiO&:_is_socket_unix",
|
||||
&fd, &type, &listening, Unicode_FSConverter, &_path))
|
||||
return NULL;
|
||||
if (_path) {
|
||||
assert(PyBytes_Check(_path));
|
||||
if (PyBytes_AsStringAndSize(_path, &path, &length))
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if (!PyArg_ParseTuple(args, "i|iiz#:_is_socket_unix",
|
||||
&fd, &type, &listening, &path, &length))
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
r = sd_is_socket_unix(fd, type, listening, path, length);
|
||||
if (set_error(r, path, NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
return PyBool_FromLong(r);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef methods[] = {
|
||||
{ "booted", booted, METH_NOARGS, booted__doc__},
|
||||
{ "notify", (PyCFunction) notify, METH_VARARGS | METH_KEYWORDS, notify__doc__},
|
||||
{ "_listen_fds", (PyCFunction) listen_fds, METH_VARARGS | METH_KEYWORDS, listen_fds__doc__},
|
||||
{ "_is_fifo", is_fifo, METH_VARARGS, is_fifo__doc__},
|
||||
{ "_is_mq", is_mq, METH_VARARGS, is_mq__doc__},
|
||||
{ "_is_socket", is_socket, METH_VARARGS, is_socket__doc__},
|
||||
{ "_is_socket_inet", is_socket_inet, METH_VARARGS, is_socket_inet__doc__},
|
||||
{ "_is_socket_unix", is_socket_unix, METH_VARARGS, is_socket_unix__doc__},
|
||||
{ NULL, NULL, 0, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
|
||||
DISABLE_WARNING_MISSING_PROTOTYPES;
|
||||
PyMODINIT_FUNC init_daemon(void) {
|
||||
PyObject *m;
|
||||
|
||||
m = Py_InitModule3("_daemon", methods, module__doc__);
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START);
|
||||
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
#else
|
||||
|
||||
static struct PyModuleDef module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_daemon", /* name of module */
|
||||
module__doc__, /* module documentation, may be NULL */
|
||||
0, /* size of per-interpreter state of the module */
|
||||
methods
|
||||
};
|
||||
|
||||
DISABLE_WARNING_MISSING_PROTOTYPES;
|
||||
PyMODINIT_FUNC PyInit__daemon(void) {
|
||||
PyObject *m;
|
||||
|
||||
m = PyModule_Create(&module);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
if (PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START) ||
|
||||
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
#endif
|
@ -1,157 +0,0 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2012 David Strauss <david@davidstrauss.net>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <alloca.h>
|
||||
#include "util.h"
|
||||
|
||||
#define SD_JOURNAL_SUPPRESS_LOCATION
|
||||
#include "systemd/sd-journal.h"
|
||||
|
||||
PyDoc_STRVAR(journal_sendv__doc__,
|
||||
"sendv('FIELD=value', 'FIELD=value', ...) -> None\n\n"
|
||||
"Send an entry to the journal."
|
||||
);
|
||||
|
||||
static PyObject *journal_sendv(PyObject *self, PyObject *args) {
|
||||
struct iovec *iov = NULL;
|
||||
int argc;
|
||||
int i, r;
|
||||
PyObject *ret = NULL;
|
||||
PyObject **encoded;
|
||||
|
||||
/* Allocate an array for the argument strings */
|
||||
argc = PyTuple_Size(args);
|
||||
encoded = alloca0(argc * sizeof(PyObject*));
|
||||
|
||||
/* Allocate sufficient iovector space for the arguments. */
|
||||
iov = alloca(argc * sizeof(struct iovec));
|
||||
|
||||
/* Iterate through the Python arguments and fill the iovector. */
|
||||
for (i = 0; i < argc; ++i) {
|
||||
PyObject *item = PyTuple_GetItem(args, i);
|
||||
char *stritem;
|
||||
Py_ssize_t length;
|
||||
|
||||
if (PyUnicode_Check(item)) {
|
||||
encoded[i] = PyUnicode_AsEncodedString(item, "utf-8", "strict");
|
||||
if (encoded[i] == NULL)
|
||||
goto out;
|
||||
item = encoded[i];
|
||||
}
|
||||
if (PyBytes_AsStringAndSize(item, &stritem, &length))
|
||||
goto out;
|
||||
|
||||
iov[i].iov_base = stritem;
|
||||
iov[i].iov_len = length;
|
||||
}
|
||||
|
||||
/* Send the iovector to the journal. */
|
||||
r = sd_journal_sendv(iov, argc);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* End with success. */
|
||||
Py_INCREF(Py_None);
|
||||
ret = Py_None;
|
||||
|
||||
out:
|
||||
for (i = 0; i < argc; ++i)
|
||||
Py_XDECREF(encoded[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(journal_stream_fd__doc__,
|
||||
"stream_fd(identifier, priority, level_prefix) -> fd\n\n"
|
||||
"Open a stream to journal by calling sd_journal_stream_fd(3)."
|
||||
);
|
||||
|
||||
static PyObject* journal_stream_fd(PyObject *self, PyObject *args) {
|
||||
const char* identifier;
|
||||
int priority, level_prefix;
|
||||
int fd;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "sii:stream_fd",
|
||||
&identifier, &priority, &level_prefix))
|
||||
return NULL;
|
||||
|
||||
fd = sd_journal_stream_fd(identifier, priority, level_prefix);
|
||||
if (fd < 0) {
|
||||
errno = -fd;
|
||||
return PyErr_SetFromErrno(PyExc_IOError);
|
||||
}
|
||||
|
||||
return PyLong_FromLong(fd);
|
||||
}
|
||||
|
||||
static PyMethodDef methods[] = {
|
||||
{ "sendv", journal_sendv, METH_VARARGS, journal_sendv__doc__ },
|
||||
{ "stream_fd", journal_stream_fd, METH_VARARGS, journal_stream_fd__doc__ },
|
||||
{ NULL, NULL, 0, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
|
||||
DISABLE_WARNING_MISSING_PROTOTYPES;
|
||||
PyMODINIT_FUNC init_journal(void) {
|
||||
PyObject *m;
|
||||
|
||||
m = Py_InitModule("_journal", methods);
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
#else
|
||||
|
||||
static struct PyModuleDef module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_journal", /* name of module */
|
||||
NULL, /* module documentation, may be NULL */
|
||||
-1, /* size of per-interpreter state of the module */
|
||||
methods
|
||||
};
|
||||
|
||||
DISABLE_WARNING_MISSING_PROTOTYPES;
|
||||
PyMODINIT_FUNC PyInit__journal(void) {
|
||||
PyObject *m;
|
||||
|
||||
m = PyModule_Create(&module);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
if (PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,55 +0,0 @@
|
||||
from ._daemon import (__version__,
|
||||
booted,
|
||||
notify,
|
||||
_listen_fds,
|
||||
_is_fifo,
|
||||
_is_socket,
|
||||
_is_socket_inet,
|
||||
_is_socket_unix,
|
||||
_is_mq,
|
||||
LISTEN_FDS_START)
|
||||
from socket import AF_UNSPEC as _AF_UNSPEC
|
||||
|
||||
def _convert_fileobj(fileobj):
|
||||
try:
|
||||
return fileobj.fileno()
|
||||
except AttributeError:
|
||||
return fileobj
|
||||
|
||||
def is_fifo(fileobj, path=None):
|
||||
fd = _convert_fileobj(fileobj)
|
||||
return _is_fifo(fd, path)
|
||||
|
||||
def is_socket(fileobj, family=_AF_UNSPEC, type=0, listening=-1):
|
||||
fd = _convert_fileobj(fileobj)
|
||||
return _is_socket(fd, family, type, listening)
|
||||
|
||||
def is_socket_inet(fileobj, family=_AF_UNSPEC, type=0, listening=-1, port=0):
|
||||
fd = _convert_fileobj(fileobj)
|
||||
return _is_socket_inet(fd, family, type, listening, port)
|
||||
|
||||
def is_socket_unix(fileobj, type=0, listening=-1, path=None):
|
||||
fd = _convert_fileobj(fileobj)
|
||||
return _is_socket_unix(fd, type, listening, path)
|
||||
|
||||
def is_mq(fileobj, path=None):
|
||||
fd = _convert_fileobj(fileobj)
|
||||
return _is_mq(fd, path)
|
||||
|
||||
def listen_fds(unset_environment=True):
|
||||
"""Return a list of socket activated descriptors
|
||||
|
||||
Example::
|
||||
|
||||
(in primary window)
|
||||
$ systemd-activate -l 2000 python3 -c \\
|
||||
'from systemd.daemon import listen_fds; print(listen_fds())'
|
||||
(in another window)
|
||||
$ telnet localhost 2000
|
||||
(in primary window)
|
||||
...
|
||||
Execing python3 (...)
|
||||
[3]
|
||||
"""
|
||||
num = _listen_fds(unset_environment)
|
||||
return list(range(LISTEN_FDS_START, LISTEN_FDS_START + num))
|
1
src/python-systemd/docs/.gitignore
vendored
1
src/python-systemd/docs/.gitignore
vendored
@ -1 +0,0 @@
|
||||
!layout.html
|
@ -1,279 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# python-systemd documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Feb 9 13:49:42 2013.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.coverage', 'sphinx.ext.viewcode']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['.']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'python-systemd'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['.']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
html_show_sourcelink = False
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'python-systemddoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'python-systemd.tex', u'python-systemd Documentation',
|
||||
None, 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'python-systemd', u'python-systemd Documentation',
|
||||
[], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output ------------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'python-systemd', u'python-systemd Documentation',
|
||||
u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks', 'python-systemd', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
|
||||
# -- Options for Epub output ---------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = u'python-systemd'
|
||||
epub_author = u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks'
|
||||
epub_publisher = u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks'
|
||||
epub_copyright = u'2013, David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
#epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
#epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
#epub_cover = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_pre_files = []
|
||||
|
||||
# HTML files shat should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
#epub_exclude_files = []
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
#epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
#epub_tocdup = True
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'http://docs.python.org/': None}
|
@ -1,18 +0,0 @@
|
||||
`systemd.daemon` module
|
||||
=======================
|
||||
|
||||
.. automodule:: systemd.daemon
|
||||
:members:
|
||||
:undoc-members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoattribute:: systemd.daemon.LISTEN_FDS_START
|
||||
|
||||
.. autofunction:: _listen_fds
|
||||
.. autofunction:: _is_fifo
|
||||
.. autofunction:: _is_socket
|
||||
.. autofunction:: _is_socket_unix
|
||||
.. autofunction:: _is_socket_inet
|
||||
.. autofunction:: _is_mq
|
||||
.. autofunction:: notify
|
||||
.. autofunction:: booted
|
@ -1,196 +0,0 @@
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 230px;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
padding: 0 20px 30px 20px;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #ffffff;
|
||||
width: 100%;
|
||||
padding: 9px 0 9px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #ffffff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: #133f52;
|
||||
line-height: 30px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
margin: 5px 10px 10px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #000000;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- hyperlink styles ------------------------------------------------------ */
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
background-color: #f2f2f2;
|
||||
font-weight: normal;
|
||||
color: #20435c;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: 20px -20px 10px -20px;
|
||||
padding: 3px 0 3px 10px;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 160%; }
|
||||
div.body h3 { font-size: 140%; }
|
||||
div.body h4 { font-size: 120%; }
|
||||
div.body h5 { font-size: 110%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #c60f0f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
text-align: justify;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.admonition p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition pre {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition ul, div.admonition ol {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 5px;
|
||||
background-color: #eeffcc;
|
||||
color: #333333;
|
||||
line-height: 120%;
|
||||
border: 1px solid #ac9;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
padding: 0 1px 0 1px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #ede;
|
||||
}
|
||||
|
||||
.warning tt {
|
||||
background: #efc2c2;
|
||||
}
|
||||
|
||||
.note tt {
|
||||
background: #d6d6d6;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
background-color: #f4debf;
|
||||
border-top: 1px solid #ac9;
|
||||
border-bottom: 1px solid #ac9;
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
`systemd.id128` module
|
||||
======================
|
||||
|
||||
.. automodule:: systemd.id128
|
||||
:members:
|
||||
:undoc-members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_COREDUMP
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_FORWARD_SYSLOG_MISSED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_HIBERNATE_KEY
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_DROPPED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_MISSED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_START
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_STOP
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_LID_CLOSED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_LID_OPENED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_OVERMOUNTING
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_POWER_KEY
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SEAT_START
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SEAT_STOP
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SESSION_START
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SESSION_STOP
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SHUTDOWN
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SLEEP_START
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SLEEP_STOP
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SPAWN_FAILED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_STARTUP_FINISHED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_SUSPEND_KEY
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_TIMEZONE_CHANGE
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_TIME_CHANGE
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_FAILED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_RELOADED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_RELOADING
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STARTED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STARTING
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STOPPED
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STOPPING
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_CONFIG_ERROR
|
||||
.. autoattribute:: systemd.id128.SD_MESSAGE_BOOTCHART
|
@ -1,24 +0,0 @@
|
||||
.. python-systemd documentation master file, created by
|
||||
sphinx-quickstart on Sat Feb 9 13:49:42 2013.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to python-systemd's documentation!
|
||||
==========================================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
journal
|
||||
id128
|
||||
daemon
|
||||
login
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
@ -1,64 +0,0 @@
|
||||
`systemd.journal` module
|
||||
========================
|
||||
|
||||
.. automodule:: systemd.journal
|
||||
:members: send, sendv, stream, stream_fd
|
||||
:undoc-members:
|
||||
|
||||
`JournalHandler` class
|
||||
----------------------
|
||||
|
||||
.. autoclass:: JournalHandler
|
||||
|
||||
Accessing the Journal
|
||||
---------------------
|
||||
|
||||
.. autoclass:: _Reader
|
||||
:undoc-members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: Reader
|
||||
:undoc-members:
|
||||
:inherited-members:
|
||||
|
||||
.. automethod:: __init__
|
||||
|
||||
.. autofunction:: _get_catalog
|
||||
.. autofunction:: get_catalog
|
||||
|
||||
.. autoclass:: Monotonic
|
||||
|
||||
.. autoattribute:: systemd.journal.DEFAULT_CONVERTERS
|
||||
|
||||
Example: polling for journal events
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This example shows that journal events can be waited for (using
|
||||
e.g. `poll`). This makes it easy to integrate Reader in an external
|
||||
event loop:
|
||||
|
||||
>>> import select
|
||||
>>> from systemd import journal
|
||||
>>> j = journal.Reader()
|
||||
>>> j.seek_tail()
|
||||
>>> p = select.poll()
|
||||
>>> p.register(j, j.get_events())
|
||||
>>> p.poll()
|
||||
[(3, 1)]
|
||||
>>> j.get_next()
|
||||
|
||||
|
||||
Journal access types
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoattribute:: systemd.journal.LOCAL_ONLY
|
||||
.. autoattribute:: systemd.journal.RUNTIME_ONLY
|
||||
.. autoattribute:: systemd.journal.SYSTEM
|
||||
.. autoattribute:: systemd.journal.CURRENT_USER
|
||||
|
||||
Journal event types
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoattribute:: systemd.journal.NOP
|
||||
.. autoattribute:: systemd.journal.APPEND
|
||||
.. autoattribute:: systemd.journal.INVALIDATE
|
@ -1,15 +0,0 @@
|
||||
{% extends "!layout.html" %}
|
||||
|
||||
{% block relbar1 %}
|
||||
<a href="../man/systemd.index.html">Index </a>·
|
||||
<a href="../man/systemd.directives.html">Directives </a>·
|
||||
<a href="index.html">Python </a>·
|
||||
<span style="float:right">systemd {{release}}</span>
|
||||
<hr />
|
||||
{% endblock %}
|
||||
|
||||
{# remove the lower relbar #}
|
||||
{% block relbar2 %} {% endblock %}
|
||||
|
||||
{# remove the footer #}
|
||||
{% block footer %} {% endblock %}
|
@ -1,28 +0,0 @@
|
||||
`systemd.login` module
|
||||
=======================
|
||||
|
||||
.. automodule:: systemd.login
|
||||
:members:
|
||||
|
||||
.. autoclass:: Monitor
|
||||
:undoc-members:
|
||||
:inherited-members:
|
||||
|
||||
Example: polling for events
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This example shows that session/uid/seat/machine events can be waited
|
||||
for (using e.g. `poll`). This makes it easy to integrate Monitor in an
|
||||
external event loop:
|
||||
|
||||
>>> import select
|
||||
>>> from systemd import login
|
||||
>>> m = login.Monitor("machine")
|
||||
>>> p = select.poll()
|
||||
>>> p.register(m, m.get_events())
|
||||
>>> login.machine_names()
|
||||
[]
|
||||
>>> p.poll()
|
||||
[(3, 1)]
|
||||
>>> login.machine_names()
|
||||
['fedora-19.nspawn']
|
@ -1,163 +0,0 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "systemd/sd-messages.h"
|
||||
|
||||
#include "pyutil.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
#include "macro.h"
|
||||
|
||||
PyDoc_STRVAR(module__doc__,
|
||||
"Python interface to the libsystemd-id128 library.\n\n"
|
||||
"Provides SD_MESSAGE_* constants and functions to query and generate\n"
|
||||
"128-bit unique identifiers."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(randomize__doc__,
|
||||
"randomize() -> UUID\n\n"
|
||||
"Return a new random 128-bit unique identifier.\n"
|
||||
"Wraps sd_id128_randomize(3)."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(get_machine__doc__,
|
||||
"get_machine() -> UUID\n\n"
|
||||
"Return a 128-bit unique identifier for this machine.\n"
|
||||
"Wraps sd_id128_get_machine(3)."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(get_boot__doc__,
|
||||
"get_boot() -> UUID\n\n"
|
||||
"Return a 128-bit unique identifier for this boot.\n"
|
||||
"Wraps sd_id128_get_boot(3)."
|
||||
);
|
||||
|
||||
static PyObject* make_uuid(sd_id128_t id) {
|
||||
_cleanup_Py_DECREF_ PyObject
|
||||
*uuid = NULL, *UUID = NULL, *bytes = NULL,
|
||||
*args = NULL, *kwargs = NULL;
|
||||
|
||||
uuid = PyImport_ImportModule("uuid");
|
||||
if (!uuid)
|
||||
return NULL;
|
||||
|
||||
UUID = PyObject_GetAttrString(uuid, "UUID");
|
||||
bytes = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes));
|
||||
args = Py_BuildValue("()");
|
||||
kwargs = PyDict_New();
|
||||
if (!UUID || !bytes || !args || !kwargs)
|
||||
return NULL;
|
||||
|
||||
if (PyDict_SetItemString(kwargs, "bytes", bytes) < 0)
|
||||
return NULL;
|
||||
|
||||
return PyObject_Call(UUID, args, kwargs);
|
||||
}
|
||||
|
||||
#define helper(name) \
|
||||
static PyObject *name(PyObject *self, PyObject *args) { \
|
||||
sd_id128_t id; \
|
||||
int r; \
|
||||
\
|
||||
assert(args == NULL); \
|
||||
\
|
||||
r = sd_id128_##name(&id); \
|
||||
if (r < 0) { \
|
||||
errno = -r; \
|
||||
return PyErr_SetFromErrno(PyExc_IOError); \
|
||||
} \
|
||||
\
|
||||
return make_uuid(id); \
|
||||
}
|
||||
|
||||
helper(randomize)
|
||||
helper(get_machine)
|
||||
helper(get_boot)
|
||||
|
||||
static PyMethodDef methods[] = {
|
||||
{ "randomize", randomize, METH_NOARGS, randomize__doc__},
|
||||
{ "get_machine", get_machine, METH_NOARGS, get_machine__doc__},
|
||||
{ "get_boot", get_boot, METH_NOARGS, get_boot__doc__},
|
||||
{ NULL, NULL, 0, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
static int add_id(PyObject *module, const char* name, sd_id128_t id) {
|
||||
PyObject *obj;
|
||||
|
||||
obj = make_uuid(id);
|
||||
if (!obj)
|
||||
return -1;
|
||||
|
||||
return PyModule_AddObject(module, name, obj);
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
|
||||
DISABLE_WARNING_MISSING_PROTOTYPES;
|
||||
PyMODINIT_FUNC initid128(void) {
|
||||
PyObject *m;
|
||||
|
||||
m = Py_InitModule3("id128", methods, module__doc__);
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
/* a series of lines like 'add_id() ;' follow */
|
||||
#define JOINER ;
|
||||
#include "id128-constants.h"
|
||||
#undef JOINER
|
||||
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
#else
|
||||
|
||||
static struct PyModuleDef module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"id128", /* name of module */
|
||||
module__doc__, /* module documentation, may be NULL */
|
||||
-1, /* size of per-interpreter state of the module */
|
||||
methods
|
||||
};
|
||||
|
||||
DISABLE_WARNING_MISSING_PROTOTYPES;
|
||||
PyMODINIT_FUNC PyInit_id128(void) {
|
||||
PyObject *m;
|
||||
|
||||
m = PyModule_Create(&module);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
if ( /* a series of lines like 'add_id() ||' follow */
|
||||
#define JOINER ||
|
||||
#include "id128-constants.h"
|
||||
#undef JOINER
|
||||
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
#endif
|
@ -1,548 +0,0 @@
|
||||
# -*- Mode: python; coding:utf-8; indent-tabs-mode: nil -*- */
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# Copyright 2012 David Strauss <david@davidstrauss.net>
|
||||
# Copyright 2012 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
|
||||
# Copyright 2012 Marti Raudsepp <marti@juffo.org>
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# systemd is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import sys as _sys
|
||||
import datetime as _datetime
|
||||
import uuid as _uuid
|
||||
import traceback as _traceback
|
||||
import os as _os
|
||||
import logging as _logging
|
||||
if _sys.version_info >= (3,3):
|
||||
from collections import ChainMap as _ChainMap
|
||||
from syslog import (LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
|
||||
LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG)
|
||||
from ._journal import __version__, sendv, stream_fd
|
||||
from ._reader import (_Reader, NOP, APPEND, INVALIDATE,
|
||||
LOCAL_ONLY, RUNTIME_ONLY,
|
||||
SYSTEM, SYSTEM_ONLY, CURRENT_USER,
|
||||
_get_catalog)
|
||||
from . import id128 as _id128
|
||||
|
||||
if _sys.version_info >= (3,):
|
||||
from ._reader import Monotonic
|
||||
else:
|
||||
Monotonic = tuple
|
||||
|
||||
def _convert_monotonic(m):
|
||||
return Monotonic((_datetime.timedelta(microseconds=m[0]),
|
||||
_uuid.UUID(bytes=m[1])))
|
||||
|
||||
def _convert_source_monotonic(s):
|
||||
return _datetime.timedelta(microseconds=int(s))
|
||||
|
||||
def _convert_realtime(t):
|
||||
return _datetime.datetime.fromtimestamp(t / 1000000)
|
||||
|
||||
def _convert_timestamp(s):
|
||||
return _datetime.datetime.fromtimestamp(int(s) / 1000000)
|
||||
|
||||
def _convert_trivial(x):
|
||||
return x
|
||||
|
||||
if _sys.version_info >= (3,):
|
||||
def _convert_uuid(s):
|
||||
return _uuid.UUID(s.decode())
|
||||
else:
|
||||
_convert_uuid = _uuid.UUID
|
||||
|
||||
DEFAULT_CONVERTERS = {
|
||||
'MESSAGE_ID': _convert_uuid,
|
||||
'_MACHINE_ID': _convert_uuid,
|
||||
'_BOOT_ID': _convert_uuid,
|
||||
'PRIORITY': int,
|
||||
'LEADER': int,
|
||||
'SESSION_ID': int,
|
||||
'USERSPACE_USEC': int,
|
||||
'INITRD_USEC': int,
|
||||
'KERNEL_USEC': int,
|
||||
'_UID': int,
|
||||
'_GID': int,
|
||||
'_PID': int,
|
||||
'SYSLOG_FACILITY': int,
|
||||
'SYSLOG_PID': int,
|
||||
'_AUDIT_SESSION': int,
|
||||
'_AUDIT_LOGINUID': int,
|
||||
'_SYSTEMD_SESSION': int,
|
||||
'_SYSTEMD_OWNER_UID': int,
|
||||
'CODE_LINE': int,
|
||||
'ERRNO': int,
|
||||
'EXIT_STATUS': int,
|
||||
'_SOURCE_REALTIME_TIMESTAMP': _convert_timestamp,
|
||||
'__REALTIME_TIMESTAMP': _convert_realtime,
|
||||
'_SOURCE_MONOTONIC_TIMESTAMP': _convert_source_monotonic,
|
||||
'__MONOTONIC_TIMESTAMP': _convert_monotonic,
|
||||
'__CURSOR': _convert_trivial,
|
||||
'COREDUMP': bytes,
|
||||
'COREDUMP_PID': int,
|
||||
'COREDUMP_UID': int,
|
||||
'COREDUMP_GID': int,
|
||||
'COREDUMP_SESSION': int,
|
||||
'COREDUMP_SIGNAL': int,
|
||||
'COREDUMP_TIMESTAMP': _convert_timestamp,
|
||||
}
|
||||
|
||||
_IDENT_LETTER = set('ABCDEFGHIJKLMNOPQRTSUVWXYZ_')
|
||||
|
||||
def _valid_field_name(s):
|
||||
return not (set(s) - _IDENT_LETTER)
|
||||
|
||||
class Reader(_Reader):
|
||||
"""Reader allows the access and filtering of systemd journal
|
||||
entries. Note that in order to access the system journal, a
|
||||
non-root user must be in the `systemd-journal` group.
|
||||
|
||||
Example usage to print out all informational or higher level
|
||||
messages for systemd-udevd for this boot:
|
||||
|
||||
>>> j = journal.Reader()
|
||||
>>> j.this_boot()
|
||||
>>> j.log_level(journal.LOG_INFO)
|
||||
>>> j.add_match(_SYSTEMD_UNIT="systemd-udevd.service")
|
||||
>>> for entry in j:
|
||||
... print(entry['MESSAGE'])
|
||||
|
||||
See systemd.journal-fields(7) for more info on typical fields
|
||||
found in the journal.
|
||||
"""
|
||||
def __init__(self, flags=0, path=None, files=None, converters=None):
|
||||
"""Create an instance of Reader, which allows filtering and
|
||||
return of journal entries.
|
||||
|
||||
Argument `flags` sets open flags of the journal, which can be one
|
||||
of, or ORed combination of constants: LOCAL_ONLY (default) opens
|
||||
journal on local machine only; RUNTIME_ONLY opens only
|
||||
volatile journal files; and SYSTEM_ONLY opens only
|
||||
journal files of system services and the kernel.
|
||||
|
||||
Argument `path` is the directory of journal files. Note that
|
||||
`flags` and `path` are exclusive.
|
||||
|
||||
Argument `converters` is a dictionary which updates the
|
||||
DEFAULT_CONVERTERS to convert journal field values. Field
|
||||
names are used as keys into this dictionary. The values must
|
||||
be single argument functions, which take a `bytes` object and
|
||||
return a converted value. When there's no entry for a field
|
||||
name, then the default UTF-8 decoding will be attempted. If
|
||||
the conversion fails with a ValueError, unconverted bytes
|
||||
object will be returned. (Note that ValueEror is a superclass
|
||||
of UnicodeDecodeError).
|
||||
|
||||
Reader implements the context manager protocol: the journal
|
||||
will be closed when exiting the block.
|
||||
"""
|
||||
super(Reader, self).__init__(flags, path, files)
|
||||
if _sys.version_info >= (3,3):
|
||||
self.converters = _ChainMap()
|
||||
if converters is not None:
|
||||
self.converters.maps.append(converters)
|
||||
self.converters.maps.append(DEFAULT_CONVERTERS)
|
||||
else:
|
||||
self.converters = DEFAULT_CONVERTERS.copy()
|
||||
if converters is not None:
|
||||
self.converters.update(converters)
|
||||
|
||||
def _convert_field(self, key, value):
|
||||
"""Convert value using self.converters[key]
|
||||
|
||||
If `key` is not present in self.converters, a standard unicode
|
||||
decoding will be attempted. If the conversion (either
|
||||
key-specific or the default one) fails with a ValueError, the
|
||||
original bytes object will be returned.
|
||||
"""
|
||||
convert = self.converters.get(key, bytes.decode)
|
||||
try:
|
||||
return convert(value)
|
||||
except ValueError:
|
||||
# Leave in default bytes
|
||||
return value
|
||||
|
||||
def _convert_entry(self, entry):
|
||||
"""Convert entire journal entry utilising _covert_field"""
|
||||
result = {}
|
||||
for key, value in entry.items():
|
||||
if isinstance(value, list):
|
||||
result[key] = [self._convert_field(key, val) for val in value]
|
||||
else:
|
||||
result[key] = self._convert_field(key, value)
|
||||
return result
|
||||
|
||||
def __iter__(self):
|
||||
"""Part of iterator protocol.
|
||||
Returns self.
|
||||
"""
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
"""Part of iterator protocol.
|
||||
Returns self.get_next() or raises StopIteration.
|
||||
"""
|
||||
ans = self.get_next()
|
||||
if ans:
|
||||
return ans
|
||||
else:
|
||||
raise StopIteration()
|
||||
|
||||
if _sys.version_info < (3,):
|
||||
next = __next__
|
||||
|
||||
def add_match(self, *args, **kwargs):
|
||||
"""Add one or more matches to the filter journal log entries.
|
||||
All matches of different field are combined in a logical AND,
|
||||
and matches of the same field are automatically combined in a
|
||||
logical OR.
|
||||
Matches can be passed as strings of form "FIELD=value", or
|
||||
keyword arguments FIELD="value".
|
||||
"""
|
||||
args = list(args)
|
||||
args.extend(_make_line(key, val) for key, val in kwargs.items())
|
||||
for arg in args:
|
||||
super(Reader, self).add_match(arg)
|
||||
|
||||
def get_next(self, skip=1):
|
||||
"""Return the next log entry as a mapping type, currently
|
||||
a standard dictionary of fields.
|
||||
|
||||
Optional skip value will return the `skip`\-th log entry.
|
||||
|
||||
Entries will be processed with converters specified during
|
||||
Reader creation.
|
||||
"""
|
||||
if super(Reader, self)._next(skip):
|
||||
entry = super(Reader, self)._get_all()
|
||||
if entry:
|
||||
entry['__REALTIME_TIMESTAMP'] = self._get_realtime()
|
||||
entry['__MONOTONIC_TIMESTAMP'] = self._get_monotonic()
|
||||
entry['__CURSOR'] = self._get_cursor()
|
||||
return self._convert_entry(entry)
|
||||
return dict()
|
||||
|
||||
def get_previous(self, skip=1):
|
||||
"""Return the previous log entry as a mapping type,
|
||||
currently a standard dictionary of fields.
|
||||
|
||||
Optional skip value will return the -`skip`\-th log entry.
|
||||
|
||||
Entries will be processed with converters specified during
|
||||
Reader creation.
|
||||
|
||||
Equivalent to get_next(-skip).
|
||||
"""
|
||||
return self.get_next(-skip)
|
||||
|
||||
def query_unique(self, field):
|
||||
"""Return unique values appearing in the journal for given `field`.
|
||||
|
||||
Note this does not respect any journal matches.
|
||||
|
||||
Entries will be processed with converters specified during
|
||||
Reader creation.
|
||||
"""
|
||||
return set(self._convert_field(field, value)
|
||||
for value in super(Reader, self).query_unique(field))
|
||||
|
||||
def wait(self, timeout=None):
|
||||
"""Wait for a change in the journal. `timeout` is the maximum
|
||||
time in seconds to wait, or None, to wait forever.
|
||||
|
||||
Returns one of NOP (no change), APPEND (new entries have been
|
||||
added to the end of the journal), or INVALIDATE (journal files
|
||||
have been added or removed).
|
||||
"""
|
||||
us = -1 if timeout is None else int(timeout * 1000000)
|
||||
return super(Reader, self).wait(us)
|
||||
|
||||
def seek_realtime(self, realtime):
|
||||
"""Seek to a matching journal entry nearest to `realtime` time.
|
||||
|
||||
Argument `realtime` must be either an integer unix timestamp
|
||||
or datetime.datetime instance.
|
||||
"""
|
||||
if isinstance(realtime, _datetime.datetime):
|
||||
realtime = float(realtime.strftime("%s.%f")) * 1000000
|
||||
return super(Reader, self).seek_realtime(int(realtime))
|
||||
|
||||
def seek_monotonic(self, monotonic, bootid=None):
|
||||
"""Seek to a matching journal entry nearest to `monotonic` time.
|
||||
|
||||
Argument `monotonic` is a timestamp from boot in either
|
||||
seconds or a datetime.timedelta instance. Argument `bootid`
|
||||
is a string or UUID representing which boot the monotonic time
|
||||
is reference to. Defaults to current bootid.
|
||||
"""
|
||||
if isinstance(monotonic, _datetime.timedelta):
|
||||
monotonic = monotonic.totalseconds()
|
||||
monotonic = int(monotonic * 1000000)
|
||||
if isinstance(bootid, _uuid.UUID):
|
||||
bootid = bootid.hex
|
||||
return super(Reader, self).seek_monotonic(monotonic, bootid)
|
||||
|
||||
def log_level(self, level):
|
||||
"""Set maximum log `level` by setting matches for PRIORITY.
|
||||
"""
|
||||
if 0 <= level <= 7:
|
||||
for i in range(level+1):
|
||||
self.add_match(PRIORITY="%d" % i)
|
||||
else:
|
||||
raise ValueError("Log level must be 0 <= level <= 7")
|
||||
|
||||
def messageid_match(self, messageid):
|
||||
"""Add match for log entries with specified `messageid`.
|
||||
|
||||
`messageid` can be string of hexadicimal digits or a UUID
|
||||
instance. Standard message IDs can be found in systemd.id128.
|
||||
|
||||
Equivalent to add_match(MESSAGE_ID=`messageid`).
|
||||
"""
|
||||
if isinstance(messageid, _uuid.UUID):
|
||||
messageid = messageid.hex
|
||||
self.add_match(MESSAGE_ID=messageid)
|
||||
|
||||
def this_boot(self, bootid=None):
|
||||
"""Add match for _BOOT_ID equal to current boot ID or the specified boot ID.
|
||||
|
||||
If specified, bootid should be either a UUID or a 32 digit hex number.
|
||||
|
||||
Equivalent to add_match(_BOOT_ID='bootid').
|
||||
"""
|
||||
if bootid is None:
|
||||
bootid = _id128.get_boot().hex
|
||||
else:
|
||||
bootid = getattr(bootid, 'hex', bootid)
|
||||
self.add_match(_BOOT_ID=bootid)
|
||||
|
||||
def this_machine(self, machineid=None):
|
||||
"""Add match for _MACHINE_ID equal to the ID of this machine.
|
||||
|
||||
If specified, machineid should be either a UUID or a 32 digit hex number.
|
||||
|
||||
Equivalent to add_match(_MACHINE_ID='machineid').
|
||||
"""
|
||||
if machineid is None:
|
||||
machineid = _id128.get_machine().hex
|
||||
else:
|
||||
machineid = getattr(machineid, 'hex', machineid)
|
||||
self.add_match(_MACHINE_ID=machineid)
|
||||
|
||||
|
||||
def get_catalog(mid):
|
||||
if isinstance(mid, _uuid.UUID):
|
||||
mid = mid.hex
|
||||
return _get_catalog(mid)
|
||||
|
||||
def _make_line(field, value):
|
||||
if isinstance(value, bytes):
|
||||
return field.encode('utf-8') + b'=' + value
|
||||
elif isinstance(value, int):
|
||||
return field + '=' + str(value)
|
||||
else:
|
||||
return field + '=' + value
|
||||
|
||||
def send(MESSAGE, MESSAGE_ID=None,
|
||||
CODE_FILE=None, CODE_LINE=None, CODE_FUNC=None,
|
||||
**kwargs):
|
||||
r"""Send a message to the journal.
|
||||
|
||||
>>> journal.send('Hello world')
|
||||
>>> journal.send('Hello, again, world', FIELD2='Greetings!')
|
||||
>>> journal.send('Binary message', BINARY=b'\xde\xad\xbe\xef')
|
||||
|
||||
Value of the MESSAGE argument will be used for the MESSAGE=
|
||||
field. MESSAGE must be a string and will be sent as UTF-8 to
|
||||
the journal.
|
||||
|
||||
MESSAGE_ID can be given to uniquely identify the type of
|
||||
message. It must be a string or a uuid.UUID object.
|
||||
|
||||
CODE_LINE, CODE_FILE, and CODE_FUNC can be specified to
|
||||
identify the caller. Unless at least on of the three is given,
|
||||
values are extracted from the stack frame of the caller of
|
||||
send(). CODE_FILE and CODE_FUNC must be strings, CODE_LINE
|
||||
must be an integer.
|
||||
|
||||
Additional fields for the journal entry can only be specified
|
||||
as keyword arguments. The payload can be either a string or
|
||||
bytes. A string will be sent as UTF-8, and bytes will be sent
|
||||
as-is to the journal.
|
||||
|
||||
Other useful fields include PRIORITY, SYSLOG_FACILITY,
|
||||
SYSLOG_IDENTIFIER, SYSLOG_PID.
|
||||
"""
|
||||
|
||||
args = ['MESSAGE=' + MESSAGE]
|
||||
|
||||
if MESSAGE_ID is not None:
|
||||
id = getattr(MESSAGE_ID, 'hex', MESSAGE_ID)
|
||||
args.append('MESSAGE_ID=' + id)
|
||||
|
||||
if CODE_LINE == CODE_FILE == CODE_FUNC == None:
|
||||
CODE_FILE, CODE_LINE, CODE_FUNC = \
|
||||
_traceback.extract_stack(limit=2)[0][:3]
|
||||
if CODE_FILE is not None:
|
||||
args.append('CODE_FILE=' + CODE_FILE)
|
||||
if CODE_LINE is not None:
|
||||
args.append('CODE_LINE={:d}'.format(CODE_LINE))
|
||||
if CODE_FUNC is not None:
|
||||
args.append('CODE_FUNC=' + CODE_FUNC)
|
||||
|
||||
args.extend(_make_line(key, val) for key, val in kwargs.items())
|
||||
return sendv(*args)
|
||||
|
||||
def stream(identifier, priority=LOG_DEBUG, level_prefix=False):
|
||||
r"""Return a file object wrapping a stream to journal.
|
||||
|
||||
Log messages written to this file as simple newline sepearted
|
||||
text strings are written to the journal.
|
||||
|
||||
The file will be line buffered, so messages are actually sent
|
||||
after a newline character is written.
|
||||
|
||||
>>> stream = journal.stream('myapp')
|
||||
>>> stream
|
||||
<open file '<fdopen>', mode 'w' at 0x...>
|
||||
>>> stream.write('message...\n')
|
||||
|
||||
will produce the following message in the journal::
|
||||
|
||||
PRIORITY=7
|
||||
SYSLOG_IDENTIFIER=myapp
|
||||
MESSAGE=message...
|
||||
|
||||
Using the interface with print might be more convinient:
|
||||
|
||||
>>> from __future__ import print_function
|
||||
>>> print('message...', file=stream)
|
||||
|
||||
priority is the syslog priority, one of `LOG_EMERG`,
|
||||
`LOG_ALERT`, `LOG_CRIT`, `LOG_ERR`, `LOG_WARNING`,
|
||||
`LOG_NOTICE`, `LOG_INFO`, `LOG_DEBUG`.
|
||||
|
||||
level_prefix is a boolean. If true, kernel-style log priority
|
||||
level prefixes (such as '<1>') are interpreted. See
|
||||
sd-daemon(3) for more information.
|
||||
"""
|
||||
|
||||
fd = stream_fd(identifier, priority, level_prefix)
|
||||
return _os.fdopen(fd, 'w', 1)
|
||||
|
||||
class JournalHandler(_logging.Handler):
|
||||
"""Journal handler class for the Python logging framework.
|
||||
|
||||
Please see the Python logging module documentation for an
|
||||
overview: http://docs.python.org/library/logging.html.
|
||||
|
||||
To create a custom logger whose messages go only to journal:
|
||||
|
||||
>>> log = logging.getLogger('custom_logger_name')
|
||||
>>> log.propagate = False
|
||||
>>> log.addHandler(journal.JournalHandler())
|
||||
>>> log.warn("Some message: %s", detail)
|
||||
|
||||
Note that by default, message levels `INFO` and `DEBUG` are
|
||||
ignored by the logging framework. To enable those log levels:
|
||||
|
||||
>>> log.setLevel(logging.DEBUG)
|
||||
|
||||
To redirect all logging messages to journal regardless of where
|
||||
they come from, attach it to the root logger:
|
||||
|
||||
>>> logging.root.addHandler(journal.JournalHandler())
|
||||
|
||||
For more complex configurations when using `dictConfig` or
|
||||
`fileConfig`, specify `systemd.journal.JournalHandler` as the
|
||||
handler class. Only standard handler configuration options
|
||||
are supported: `level`, `formatter`, `filters`.
|
||||
|
||||
To attach journal MESSAGE_ID, an extra field is supported:
|
||||
|
||||
>>> import uuid
|
||||
>>> mid = uuid.UUID('0123456789ABCDEF0123456789ABCDEF')
|
||||
>>> log.warn("Message with ID", extra={'MESSAGE_ID': mid})
|
||||
|
||||
Fields to be attached to all messages sent through this
|
||||
handler can be specified as keyword arguments. This probably
|
||||
makes sense only for SYSLOG_IDENTIFIER and similar fields
|
||||
which are constant for the whole program:
|
||||
|
||||
>>> journal.JournalHandler(SYSLOG_IDENTIFIER='my-cool-app')
|
||||
|
||||
The following journal fields will be sent:
|
||||
`MESSAGE`, `PRIORITY`, `THREAD_NAME`, `CODE_FILE`, `CODE_LINE`,
|
||||
`CODE_FUNC`, `LOGGER` (name as supplied to getLogger call),
|
||||
`MESSAGE_ID` (optional, see above), `SYSLOG_IDENTIFIER` (defaults
|
||||
to sys.argv[0]).
|
||||
"""
|
||||
|
||||
def __init__(self, level=_logging.NOTSET, **kwargs):
|
||||
super(JournalHandler, self).__init__(level)
|
||||
|
||||
for name in kwargs:
|
||||
if not _valid_field_name(name):
|
||||
raise ValueError('Invalid field name: ' + name)
|
||||
if 'SYSLOG_IDENTIFIER' not in kwargs:
|
||||
kwargs['SYSLOG_IDENTIFIER'] = _sys.argv[0]
|
||||
self._extra = kwargs
|
||||
|
||||
def emit(self, record):
|
||||
"""Write record as journal event.
|
||||
|
||||
MESSAGE is taken from the message provided by the
|
||||
user, and PRIORITY, LOGGER, THREAD_NAME,
|
||||
CODE_{FILE,LINE,FUNC} fields are appended
|
||||
automatically. In addition, record.MESSAGE_ID will be
|
||||
used if present.
|
||||
"""
|
||||
try:
|
||||
msg = self.format(record)
|
||||
pri = self.mapPriority(record.levelno)
|
||||
mid = getattr(record, 'MESSAGE_ID', None)
|
||||
send(msg,
|
||||
MESSAGE_ID=mid,
|
||||
PRIORITY=format(pri),
|
||||
LOGGER=record.name,
|
||||
THREAD_NAME=record.threadName,
|
||||
CODE_FILE=record.pathname,
|
||||
CODE_LINE=record.lineno,
|
||||
CODE_FUNC=record.funcName,
|
||||
**self._extra)
|
||||
except Exception:
|
||||
self.handleError(record)
|
||||
|
||||
@staticmethod
|
||||
def mapPriority(levelno):
|
||||
"""Map logging levels to journald priorities.
|
||||
|
||||
Since Python log level numbers are "sparse", we have
|
||||
to map numbers in between the standard levels too.
|
||||
"""
|
||||
if levelno <= _logging.DEBUG:
|
||||
return LOG_DEBUG
|
||||
elif levelno <= _logging.INFO:
|
||||
return LOG_INFO
|
||||
elif levelno <= _logging.WARNING:
|
||||
return LOG_WARNING
|
||||
elif levelno <= _logging.ERROR:
|
||||
return LOG_ERR
|
||||
elif levelno <= _logging.CRITICAL:
|
||||
return LOG_CRIT
|
||||
else:
|
||||
return LOG_ALERT
|
@ -1,376 +0,0 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
#include <Python.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include "systemd/sd-login.h"
|
||||
#include "pyutil.h"
|
||||
#include "util.h"
|
||||
#include "strv.h"
|
||||
|
||||
PyDoc_STRVAR(module__doc__,
|
||||
"Python interface to the libsystemd-login library."
|
||||
);
|
||||
|
||||
#define helper(name) \
|
||||
static PyObject* name(PyObject *self, PyObject *args) { \
|
||||
_cleanup_strv_free_ char **list = NULL; \
|
||||
int r; \
|
||||
PyObject *ans; \
|
||||
\
|
||||
assert(args == NULL); \
|
||||
\
|
||||
r = sd_get_##name(&list); \
|
||||
if (r < 0) { \
|
||||
errno = -r; \
|
||||
return PyErr_SetFromErrno(PyExc_IOError); \
|
||||
} \
|
||||
\
|
||||
ans = PyList_New(r); \
|
||||
if (!ans) \
|
||||
return NULL; \
|
||||
\
|
||||
for (r--; r >= 0; r--) { \
|
||||
PyObject *s = unicode_FromString(list[r]); \
|
||||
if (!s) { \
|
||||
Py_DECREF(ans); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
PyList_SetItem(ans, r, s); \
|
||||
} \
|
||||
\
|
||||
return ans; \
|
||||
}
|
||||
|
||||
helper(seats)
|
||||
helper(sessions)
|
||||
helper(machine_names)
|
||||
#undef helper
|
||||
|
||||
static PyObject* uids(PyObject *self, PyObject *args) {
|
||||
_cleanup_free_ uid_t *list = NULL;
|
||||
int r;
|
||||
PyObject *ans;
|
||||
|
||||
assert(args == NULL);
|
||||
|
||||
r = sd_get_uids(&list);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
return PyErr_SetFromErrno(PyExc_IOError);
|
||||
}
|
||||
|
||||
ans = PyList_New(r);
|
||||
if (!ans)
|
||||
return NULL;
|
||||
|
||||
for (r--; r >= 0; r--) {
|
||||
PyObject *s = long_FromLong(list[r]);
|
||||
if (!s) {
|
||||
Py_DECREF(ans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyList_SetItem(ans, r, s);
|
||||
}
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(seats__doc__,
|
||||
"seats() -> list\n\n"
|
||||
"Returns a list of currently available local seats.\n"
|
||||
"Wraps sd_get_seats(3)."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(sessions__doc__,
|
||||
"sessions() -> list\n\n"
|
||||
"Returns a list of current login sessions.\n"
|
||||
"Wraps sd_get_sessions(3)."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(machine_names__doc__,
|
||||
"machine_names() -> list\n\n"
|
||||
"Returns a list of currently running virtual machines\n"
|
||||
"and containers on the system.\n"
|
||||
"Wraps sd_get_machine_names(3)."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(uids__doc__,
|
||||
"uids() -> list\n\n"
|
||||
"Returns a list of uids of users who currently have login sessions.\n"
|
||||
"Wraps sd_get_uids(3)."
|
||||
);
|
||||
|
||||
static PyMethodDef methods[] = {
|
||||
{ "seats", seats, METH_NOARGS, seats__doc__},
|
||||
{ "sessions", sessions, METH_NOARGS, sessions__doc__},
|
||||
{ "machine_names", machine_names, METH_NOARGS, machine_names__doc__},
|
||||
{ "uids", uids, METH_NOARGS, uids__doc__},
|
||||
{} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
sd_login_monitor *monitor;
|
||||
} Monitor;
|
||||
static PyTypeObject MonitorType;
|
||||
|
||||
static void Monitor_dealloc(Monitor* self) {
|
||||
sd_login_monitor_unref(self->monitor);
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Monitor__doc__,
|
||||
"Monitor([category]) -> ...\n\n"
|
||||
"Monitor may be used to monitor login sessions, users, seats,\n"
|
||||
"and virtual machines/containers. Monitor provides a file\n"
|
||||
"descriptor which can be integrated in an external event loop.\n"
|
||||
"See man:sd_login_monitor_new(3) for the details about what\n"
|
||||
"can be monitored.");
|
||||
static int Monitor_init(Monitor *self, PyObject *args, PyObject *keywds) {
|
||||
const char *category = NULL;
|
||||
int r;
|
||||
|
||||
static const char* const kwlist[] = {"category", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|z:__init__", (char**) kwlist,
|
||||
&category))
|
||||
return -1;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = sd_login_monitor_new(category, &self->monitor);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
return set_error(r, NULL, "Invalid category");
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Monitor_fileno__doc__,
|
||||
"fileno() -> int\n\n"
|
||||
"Get a file descriptor to poll for events.\n"
|
||||
"This method wraps sd_login_monitor_get_fd(3).");
|
||||
static PyObject* Monitor_fileno(Monitor *self, PyObject *args) {
|
||||
int fd = sd_login_monitor_get_fd(self->monitor);
|
||||
set_error(fd, NULL, NULL);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
return long_FromLong(fd);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Monitor_get_events__doc__,
|
||||
"get_events() -> int\n\n"
|
||||
"Returns a mask of poll() events to wait for on the file\n"
|
||||
"descriptor returned by .fileno().\n\n"
|
||||
"See man:sd_login_monitor_get_events(3) for further discussion.");
|
||||
static PyObject* Monitor_get_events(Monitor *self, PyObject *args) {
|
||||
int r = sd_login_monitor_get_events(self->monitor);
|
||||
set_error(r, NULL, NULL);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
return long_FromLong(r);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Monitor_get_timeout__doc__,
|
||||
"get_timeout() -> int or None\n\n"
|
||||
"Returns a timeout value for usage in poll(), the time since the\n"
|
||||
"epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
|
||||
"is necessary.\n\n"
|
||||
"The return value must be converted to a relative timeout in\n"
|
||||
"milliseconds if it is to be used as an argument for poll().\n"
|
||||
"See man:sd_login_monitor_get_timeout(3) for further discussion.");
|
||||
static PyObject* Monitor_get_timeout(Monitor *self, PyObject *args) {
|
||||
int r;
|
||||
uint64_t t;
|
||||
|
||||
r = sd_login_monitor_get_timeout(self->monitor, &t);
|
||||
set_error(r, NULL, NULL);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
if (t == (uint64_t) -1)
|
||||
Py_RETURN_NONE;
|
||||
|
||||
assert_cc(sizeof(unsigned long long) == sizeof(t));
|
||||
return PyLong_FromUnsignedLongLong(t);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Monitor_get_timeout_ms__doc__,
|
||||
"get_timeout_ms() -> int\n\n"
|
||||
"Returns a timeout value suitable for usage in poll(), the value\n"
|
||||
"returned by .get_timeout() converted to relative ms, or -1 if\n"
|
||||
"no timeout is necessary.");
|
||||
static PyObject* Monitor_get_timeout_ms(Monitor *self, PyObject *args) {
|
||||
int r;
|
||||
uint64_t t;
|
||||
|
||||
r = sd_login_monitor_get_timeout(self->monitor, &t);
|
||||
set_error(r, NULL, NULL);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
return absolute_timeout(t);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Monitor_close__doc__,
|
||||
"close() -> None\n\n"
|
||||
"Free resources allocated by this Monitor object.\n"
|
||||
"This method invokes sd_login_monitor_unref().\n"
|
||||
"See man:sd_login_monitor_unref(3).");
|
||||
static PyObject* Monitor_close(Monitor *self, PyObject *args) {
|
||||
assert(self);
|
||||
assert(!args);
|
||||
|
||||
sd_login_monitor_unref(self->monitor);
|
||||
self->monitor = NULL;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Monitor_flush__doc__,
|
||||
"flush() -> None\n\n"
|
||||
"Reset the wakeup state of the monitor object.\n"
|
||||
"This method invokes sd_login_monitor_flush().\n"
|
||||
"See man:sd_login_monitor_flush(3).");
|
||||
static PyObject* Monitor_flush(Monitor *self, PyObject *args) {
|
||||
assert(self);
|
||||
assert(!args);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sd_login_monitor_flush(self->monitor);
|
||||
Py_END_ALLOW_THREADS
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Monitor___enter____doc__,
|
||||
"__enter__() -> self\n\n"
|
||||
"Part of the context manager protocol.\n"
|
||||
"Returns self.\n");
|
||||
static PyObject* Monitor___enter__(PyObject *self, PyObject *args) {
|
||||
assert(self);
|
||||
assert(!args);
|
||||
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Monitor___exit____doc__,
|
||||
"__exit__(type, value, traceback) -> None\n\n"
|
||||
"Part of the context manager protocol.\n"
|
||||
"Closes the monitor..\n");
|
||||
static PyObject* Monitor___exit__(Monitor *self, PyObject *args) {
|
||||
return Monitor_close(self, args);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef Monitor_methods[] = {
|
||||
{"fileno", (PyCFunction) Monitor_fileno, METH_NOARGS, Monitor_fileno__doc__},
|
||||
{"get_events", (PyCFunction) Monitor_get_events, METH_NOARGS, Monitor_get_events__doc__},
|
||||
{"get_timeout", (PyCFunction) Monitor_get_timeout, METH_NOARGS, Monitor_get_timeout__doc__},
|
||||
{"get_timeout_ms", (PyCFunction) Monitor_get_timeout_ms, METH_NOARGS, Monitor_get_timeout_ms__doc__},
|
||||
{"close", (PyCFunction) Monitor_close, METH_NOARGS, Monitor_close__doc__},
|
||||
{"flush", (PyCFunction) Monitor_flush, METH_NOARGS, Monitor_flush__doc__},
|
||||
{"__enter__", (PyCFunction) Monitor___enter__, METH_NOARGS, Monitor___enter____doc__},
|
||||
{"__exit__", (PyCFunction) Monitor___exit__, METH_VARARGS, Monitor___exit____doc__},
|
||||
{} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject MonitorType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
.tp_name = "login.Monitor",
|
||||
.tp_basicsize = sizeof(Monitor),
|
||||
.tp_dealloc = (destructor) Monitor_dealloc,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
||||
.tp_doc = Monitor__doc__,
|
||||
.tp_methods = Monitor_methods,
|
||||
.tp_init = (initproc) Monitor_init,
|
||||
.tp_new = PyType_GenericNew,
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
|
||||
DISABLE_WARNING_MISSING_PROTOTYPES;
|
||||
PyMODINIT_FUNC initlogin(void) {
|
||||
PyObject *m;
|
||||
|
||||
if (PyType_Ready(&MonitorType) < 0)
|
||||
return;
|
||||
|
||||
m = Py_InitModule3("login", methods, module__doc__);
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
|
||||
|
||||
Py_INCREF(&MonitorType);
|
||||
PyModule_AddObject(m, "Monitor", (PyObject *) &MonitorType);
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
#else
|
||||
|
||||
static struct PyModuleDef module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"login", /* name of module */
|
||||
module__doc__, /* module documentation, may be NULL */
|
||||
-1, /* size of per-interpreter state of the module */
|
||||
methods
|
||||
};
|
||||
|
||||
DISABLE_WARNING_MISSING_PROTOTYPES;
|
||||
PyMODINIT_FUNC PyInit_login(void) {
|
||||
PyObject *m;
|
||||
|
||||
if (PyType_Ready(&MonitorType) < 0)
|
||||
return NULL;
|
||||
|
||||
m = PyModule_Create(&module);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
if (PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(&MonitorType);
|
||||
if (PyModule_AddObject(m, "Monitor", (PyObject *) &MonitorType)) {
|
||||
Py_DECREF(&MonitorType);
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
REENABLE_WARNING;
|
||||
|
||||
#endif
|
@ -1,80 +0,0 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <Python.h>
|
||||
#include "pyutil.h"
|
||||
|
||||
void cleanup_Py_DECREFp(PyObject **p) {
|
||||
if (!*p)
|
||||
return;
|
||||
|
||||
Py_DECREF(*p);
|
||||
}
|
||||
|
||||
PyObject* absolute_timeout(uint64_t t) {
|
||||
if (t == (uint64_t) -1)
|
||||
return PyLong_FromLong(-1);
|
||||
else {
|
||||
struct timespec ts;
|
||||
uint64_t n;
|
||||
int msec;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||
msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
|
||||
|
||||
return PyLong_FromLong(msec);
|
||||
}
|
||||
}
|
||||
|
||||
int set_error(int r, const char* path, const char* invalid_message) {
|
||||
if (r >= 0)
|
||||
return r;
|
||||
if (r == -EINVAL && invalid_message)
|
||||
PyErr_SetString(PyExc_ValueError, invalid_message);
|
||||
else if (r == -ENOMEM)
|
||||
PyErr_SetString(PyExc_MemoryError, "Not enough memory");
|
||||
else {
|
||||
errno = -r;
|
||||
PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
|
||||
int Unicode_FSConverter(PyObject* obj, void *_result) {
|
||||
PyObject **result = _result;
|
||||
|
||||
assert(result);
|
||||
|
||||
if (!obj)
|
||||
/* cleanup: we don't return Py_CLEANUP_SUPPORTED, so
|
||||
* we can assume that it was PyUnicode_FSConverter. */
|
||||
return PyUnicode_FSConverter(obj, result);
|
||||
|
||||
if (obj == Py_None) {
|
||||
*result = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return PyUnicode_FSConverter(obj, result);
|
||||
}
|
||||
#endif
|
@ -1,54 +0,0 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#ifndef Py_TYPE
|
||||
/* avoid duplication warnings from errors in Python 2.7 headers */
|
||||
# include <Python.h>
|
||||
#endif
|
||||
|
||||
void cleanup_Py_DECREFp(PyObject **p);
|
||||
PyObject* absolute_timeout(uint64_t t);
|
||||
int set_error(int r, const char* path, const char* invalid_message);
|
||||
|
||||
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
|
||||
int Unicode_FSConverter(PyObject* obj, void *_result);
|
||||
#endif
|
||||
|
||||
#define _cleanup_Py_DECREF_ __attribute__((cleanup(cleanup_Py_DECREFp)))
|
||||
|
||||
#if PY_MAJOR_VERSION >=3
|
||||
# define unicode_FromStringAndSize PyUnicode_FromStringAndSize
|
||||
# define unicode_FromString PyUnicode_FromString
|
||||
# define long_FromLong PyLong_FromLong
|
||||
# define long_FromSize_t PyLong_FromSize_t
|
||||
# define long_Check PyLong_Check
|
||||
# define long_AsLong PyLong_AsLong
|
||||
#else
|
||||
/* Python 3 type naming convention is used */
|
||||
# define unicode_FromStringAndSize PyString_FromStringAndSize
|
||||
# define unicode_FromString PyString_FromString
|
||||
# define long_FromLong PyInt_FromLong
|
||||
# define long_FromSize_t PyInt_FromSize_t
|
||||
# define long_Check PyInt_Check
|
||||
# define long_AsLong PyInt_AsLong
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user