Merge branch 'journal'

This commit is contained in:
Lennart Poettering 2011-12-31 00:59:37 +01:00
commit dc1ecd78e9
67 changed files with 10906 additions and 385 deletions

8
.gitignore vendored
View file

@ -1,3 +1,9 @@
/libsystemd-journal.pc
/libsystemd-id128.pc
systemd-journalctl
systemd-journald
test-id128
test-journal
test-install
org.freedesktop.hostname1.xml
org.freedesktop.locale1.xml
@ -91,7 +97,7 @@ install-sh
missing
stamp-*
*.stamp
Makefile
/Makefile
ltmain.sh
*.tar.bz2
*.tar.gz

View file

@ -27,6 +27,14 @@ LIBSYSTEMD_DAEMON_CURRENT=0
LIBSYSTEMD_DAEMON_REVISION=0
LIBSYSTEMD_DAEMON_AGE=0
LIBSYSTEMD_ID128_CURRENT=0
LIBSYSTEMD_ID128_REVISION=0
LIBSYSTEMD_ID128_AGE=0
LIBSYSTEMD_JOURNAL_CURRENT=0
LIBSYSTEMD_JOURNAL_REVISION=0
LIBSYSTEMD_JOURNAL_AGE=0
# Dirs of external packages
dbuspolicydir=@dbuspolicydir@
dbussessionservicedir=@dbussessionservicedir@
@ -141,7 +149,8 @@ rootbin_PROGRAMS = \
systemd-ask-password \
systemd-tty-ask-password-agent \
systemd-tmpfiles \
systemd-machine-id-setup
systemd-machine-id-setup \
systemd-journalctl
bin_PROGRAMS = \
systemd-cgls \
@ -180,7 +189,8 @@ rootlibexec_PROGRAMS = \
systemd-detect-virt \
systemd-sysctl \
systemd-logind \
systemd-uaccess
systemd-uaccess \
systemd-journald
if ENABLE_BINFMT
rootlibexec_PROGRAMS += \
@ -215,11 +225,15 @@ endif
lib_LTLIBRARIES = \
libsystemd-daemon.la \
libsystemd-login.la
libsystemd-login.la \
libsystemd-id128.la \
libsystemd-journal.la
pkginclude_HEADERS = \
src/sd-daemon.h \
src/sd-login.h
src/sd-login.h \
src/sd-id128.h \
src/journal/sd-journal.h
noinst_PROGRAMS = \
test-engine \
@ -232,7 +246,9 @@ noinst_PROGRAMS = \
test-env-replace \
test-strv \
test-login \
test-install
test-install \
test-id128 \
test-journal
if HAVE_PAM
pamlib_LTLIBRARIES = \
@ -385,7 +401,8 @@ dist_systemunit_DATA = \
units/quotaon.service \
units/systemd-ask-password-wall.path \
units/systemd-ask-password-console.path \
units/syslog.target
units/syslog.target \
units/systemd-journald.socket
if HAVE_SYSV_COMPAT
dist_systemunit_DATA += \
@ -406,6 +423,7 @@ nodist_systemunit_DATA = \
units/systemd-stdout-syslog-bridge.service \
units/systemd-shutdownd.service \
units/systemd-logind.service \
units/systemd-journald.service \
units/systemd-kmsg-syslogd.service \
units/systemd-modules-load.service \
units/systemd-vconsole-setup.service \
@ -469,7 +487,8 @@ EXTRA_DIST = \
units/systemd-stdout-syslog-bridge.service.in \
units/systemd-shutdownd.service.in \
units/systemd-logind.service.in \
units/systemd-kmsg-syslogd.service.in \
units/systemd-journald.service.in \
units/systemd-kmsg-syslogd.service.in \
units/systemd-modules-load.service.in \
units/systemd-vconsole-setup.service.in \
units/systemd-remount-api-vfs.service.in \
@ -498,11 +517,16 @@ EXTRA_DIST = \
systemd.pc.in \
libsystemd-daemon.pc.in \
libsystemd-login.pc.in \
libsystemd-id128.pc.in \
libsystemd-journal.pc.in \
src/libsystemd-daemon.sym \
src/libsystemd-login.sym \
src/libsystemd-id128.sym \
src/libsystemd-journal.sym \
introspect.awk \
src/73-seat-late.rules.in \
src/99-systemd.rules.in
src/99-systemd.rules.in \
man/custom-html.xsl
if ENABLE_BINFMT
EXTRA_DIST += \
@ -597,7 +621,9 @@ pkgconfigdata_DATA = \
pkgconfiglib_DATA = \
libsystemd-daemon.pc \
libsystemd-login.pc
libsystemd-login.pc \
libsystemd-id128.pc \
libsystemd-journal.pc
# Passed through intltool only
polkitpolicy_in_files = \
@ -709,7 +735,8 @@ libsystemd_core_la_SOURCES = \
src/dbus-common.c \
src/sd-daemon.c \
src/install.c \
src/cgroup-attr.c
src/cgroup-attr.c \
src/sd-id128.c
nodist_libsystemd_core_la_SOURCES = \
src/load-fragment-gperf.c \
@ -772,7 +799,14 @@ EXTRA_DIST += \
src/logind-user.h \
src/logind-acl.h \
src/dbus-loop.h \
src/spawn-agent.h
src/spawn-agent.h \
src/journal/journal-def.h \
src/journal/journal-internal.h \
src/journal/journal-file.h \
src/journal/lookup3.h \
src/journal/compress.h \
src/journal/journal-rate-limit.h \
src/acl-util.h
MANPAGES = \
man/systemd.1 \
@ -802,6 +836,7 @@ MANPAGES = \
man/daemon.7 \
man/sd-daemon.7 \
man/sd-readahead.7 \
man/sd-login.7 \
man/runlevel.8 \
man/telinit.8 \
man/halt.8 \
@ -820,7 +855,13 @@ MANPAGES = \
man/modules-load.d.5 \
man/sysctl.d.5 \
man/systemd-ask-password.1 \
man/systemd-loginctl.1
man/systemd-loginctl.1 \
man/sd_pid_get_session.3 \
man/sd_uid_get_state.3 \
man/sd_session_is_active.3 \
man/sd_seat_get_active.3 \
man/sd_get_seats.3 \
man/sd_login_monitor_new.3
if ENABLE_BINFMT
MANPAGES += \
@ -833,16 +874,44 @@ MANPAGES_ALIAS = \
man/sd_is_socket.3 \
man/sd_is_socket_unix.3 \
man/sd_is_socket_inet.3 \
man/sd_is_mq.3 \
man/sd_notifyf.3 \
man/init.1
man/init.1 \
man/sd_session_get_uid.3 \
man/sd_session_get_seat.3 \
man/sd_pid_get_owner_uid.3 \
man/sd_uid_is_on_seat.3 \
man/sd_uid_get_sessions.3 \
man/sd_uid_get_seats.3 \
man/sd_seat_get_sessions.3 \
man/sd_seat_can_multi_session.3 \
man/sd_get_sessions.3 \
man/sd_get_uids.3 \
man/sd_login_monitor_unref.3 \
man/sd_login_monitor_flush.3 \
man/sd_login_monitor_get_fd.3
man/reboot.8: man/halt.8
man/poweroff.8: man/halt.8
man/sd_is_socket.3: man/sd_is_fifo.3
man/sd_is_socket_unix.3: man/sd_is_fifo.3
man/sd_is_socket_inet.3: man/sd_is_fifo.3
man/sd_is_mq.3: man/sd_is_fifo.3
man/sd_notifyf.3: man/sd_notify.3
man/init.1: man/systemd.1
man/sd_session_get_uid.3: man/sd_session_is_active.3
man/sd_session_get_seat.3: man/sd_session_is_active.3
man/sd_pid_get_owner_uid.3: man/sd_pid_get_session.3
man/sd_uid_is_on_seat.3: man/sd_uid_get_state.3
man/sd_uid_get_sessions.3: man/sd_uid_get_state.3
man/sd_uid_get_seats.3: man/sd_uid_get_state.3
man/sd_seat_get_sessions.3: man/sd_seat_get_active.3
man/sd_seat_can_multi_session.3: man/sd_seat_get_active.3
man/sd_get_sessions.3: man/sd_get_seats.3
man/sd_get_uids.3: man/sd_get_seats.3
man/sd_login_monitor_unref.3: man/sd_login_monitor_new.3
man/sd_login_monitor_flush.3: man/sd_login_monitor_new.3
man/sd_login_monitor_get_fd.3: man/sd_login_monitor_new.3
dist_man_MANS = \
$(MANPAGES) \
@ -971,6 +1040,90 @@ test_install_CFLAGS = \
test_install_LDADD = \
libsystemd-basic.la
test_id128_SOURCES = \
src/test-id128.c \
src/sd-id128.c
test_id128_CFLAGS = \
$(AM_CFLAGS)
test_id128_LDADD = \
libsystemd-basic.la
test_journal_SOURCES = \
src/journal/test-journal.c \
src/journal/sd-journal.c \
src/journal/journal-file.c \
src/journal/lookup3.c \
src/journal/journal-send.c \
src/sd-id128.c
test_journal_CFLAGS = \
$(AM_CFLAGS)
test_journal_LDADD = \
libsystemd-basic.la
if HAVE_XZ
test_journal_SOURCES += \
src/journal/compress.c
test_journal_CFLAGS += \
$(XZ_CFLAGS)
test_journal_LDADD += \
$(XZ_LIBS)
endif
systemd_journald_SOURCES = \
src/journal/journald.c \
src/journal/sd-journal.c \
src/journal/journal-file.c \
src/journal/lookup3.c \
src/journal/journal-rate-limit.c \
src/sd-id128.c \
src/acl-util.c \
src/cgroup-util.c
systemd_journald_CFLAGS = \
$(AM_CFLAGS) \
$(ACL_CFLAGS)
systemd_journald_LDADD = \
libsystemd-basic.la \
libsystemd-daemon.la \
$(ACL_LIBS)
if HAVE_XZ
systemd_journald_SOURCES += \
src/journal/compress.c
systemd_journald_CFLAGS += \
$(XZ_CFLAGS)
systemd_journald_LDADD += \
$(XZ_LIBS)
endif
systemd_journalctl_SOURCES = \
src/journal/journalctl.c \
src/journal/sd-journal.c \
src/journal/journal-file.c \
src/journal/lookup3.c \
src/sd-id128.c \
src/pager.c
systemd_journalctl_CFLAGS = \
$(AM_CFLAGS)
systemd_journalctl_LDADD = \
libsystemd-basic.la
if HAVE_XZ
systemd_journalctl_SOURCES += \
src/journal/compress.c
systemd_journalctl_CFLAGS += \
$(XZ_CFLAGS)
systemd_journalctl_LDADD += \
$(XZ_LIBS)
endif
systemd_stdout_syslog_bridge_SOURCES = \
src/stdout-syslog-bridge.c \
src/tcpwrap.c
@ -1115,10 +1268,12 @@ systemd_uaccess_SOURCES = \
if HAVE_ACL
systemd_logind_SOURCES += \
src/logind-acl.c
src/logind-acl.c \
src/acl-util.c
systemd_uaccess_SOURCES += \
src/logind-acl.c
src/logind-acl.c \
src/acl-util.c
endif
systemd_uaccess_CFLAGS = \
@ -1166,7 +1321,8 @@ systemd_tmpfiles_LDADD = \
systemd_machine_id_setup_SOURCES = \
src/machine-id-setup.c \
src/machine-id-main.c
src/machine-id-main.c \
src/sd-id128.c
systemd_machine_id_setup_CFLAGS = \
$(AM_CFLAGS)
@ -1592,6 +1748,69 @@ libsystemd-login-install-hook:
libsystemd-login-uninstall-hook:
rm -f $(DESTDIR)$(rootlibdir)/libsystemd-login.so*
libsystemd_id128_la_SOURCES = \
src/sd-id128.c
libsystemd_id128_la_CFLAGS = \
$(AM_CFLAGS) \
-fvisibility=hidden
libsystemd_id128_la_LDFLAGS = \
-shared \
-version-info $(LIBSYSTEMD_ID128_CURRENT):$(LIBSYSTEMD_ID128_REVISION):$(LIBSYSTEMD_ID128_AGE) \
-Wl,--version-script=$(top_srcdir)/src/libsystemd-id128.sym
libsystemd_id128_la_LIBADD = \
libsystemd-basic.la
# move lib from $(libdir) to $(rootlibdir) and update devel link, if needed
libsystemd-id128-install-hook:
if test "$(libdir)" != "$(rootlibdir)"; then \
mkdir -p $(DESTDIR)$(rootlibdir) && \
so_img_name=$$(readlink $(DESTDIR)$(libdir)/libsystemd-id128.so) && \
so_img_rel_target_prefix=$$(echo $(libdir) | sed 's,\(^/\|\)[^/][^/]*,..,g') && \
ln -sf $$so_img_rel_target_prefix$(rootlibdir)/$$so_img_name $(DESTDIR)$(libdir)/libsystemd-id128.so && \
mv $(DESTDIR)$(libdir)/libsystemd-id128.so.* $(DESTDIR)$(rootlibdir); \
fi
libsystemd-id128-uninstall-hook:
rm -f $(DESTDIR)$(rootlibdir)/libsystemd-id128.so*
libsystemd_journal_la_SOURCES = \
src/journal/sd-journal.c \
src/journal/journal-file.c \
src/journal/compress.c \
src/journal/lookup3.c \
src/journal/journal-send.c
libsystemd_journal_la_CFLAGS = \
$(AM_CFLAGS) \
$(XZ_CFLAGS) \
-fvisibility=hidden
libsystemd_journal_la_LDFLAGS = \
-shared \
-version-info $(LIBSYSTEMD_JOURNAL_CURRENT):$(LIBSYSTEMD_JOURNAL_REVISION):$(LIBSYSTEMD_JOURNAL_AGE) \
-Wl,--version-script=$(top_srcdir)/src/libsystemd-journal.sym
libsystemd_journal_la_LIBADD = \
libsystemd-basic.la \
libsystemd-id128.la \
$(XZ_LIBS)
# move lib from $(libdir) to $(rootlibdir) and update devel link, if needed
libsystemd-journal-install-hook:
if test "$(libdir)" != "$(rootlibdir)"; then \
mkdir -p $(DESTDIR)$(rootlibdir) && \
so_img_name=$$(readlink $(DESTDIR)$(libdir)/libsystemd-journal.so) && \
so_img_rel_target_prefix=$$(echo $(libdir) | sed 's,\(^/\|\)[^/][^/]*,..,g') && \
ln -sf $$so_img_rel_target_prefix$(rootlibdir)/$$so_img_name $(DESTDIR)$(libdir)/libsystemd-journal.so && \
mv $(DESTDIR)$(libdir)/libsystemd-journal.so.* $(DESTDIR)$(rootlibdir); \
fi
libsystemd-journal-uninstall-hook:
rm -f $(DESTDIR)$(rootlibdir)/libsystemd-journal.so*
SED_PROCESS = \
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
$(SED) -e 's,@rootlibexecdir\@,$(rootlibexecdir),g' \
@ -1677,7 +1896,7 @@ endif
if HAVE_XSLTPROC
XSLTPROC_FLAGS = \
--nonet \
--param funcsynopsis.style "'ansi'"
--stringparam funcsynopsis.style ansi
XSLTPROC_PROCESS_MAN = \
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
@ -1690,11 +1909,11 @@ XSLTPROC_PROCESS_MAN_IN = \
XSLTPROC_PROCESS_HTML = \
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/xhtml-1_1/docbook.xsl $<
$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) man/custom-html.xsl $<
XSLTPROC_PROCESS_HTML_IN = \
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
$(XSLTPROC) -o ${@:.in=} $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/xhtml-1_1/docbook.xsl $< && \
$(XSLTPROC) -o ${@:.in=} $(XSLTPROC_FLAGS) man/custom-html.xsl $< && \
mv ${@:.in=} $@
man/%.1: man/%.xml
@ -1808,11 +2027,12 @@ endif
rm -f user && \
$(LN_S) $(pkgsysconfdir)/user user )
( cd $(DESTDIR)$(systemunitdir)/sockets.target.wants && \
rm -f systemd-initctl.socket systemd-stdout-syslog-bridge.socket systemd-shutdownd.socket syslog.socket && \
rm -f systemd-initctl.socket systemd-stdout-syslog-bridge.socket systemd-shutdownd.socket syslog.socket systemd-journald.socket && \
$(LN_S) ../systemd-stdout-syslog-bridge.socket systemd-stdout-syslog-bridge.socket && \
$(LN_S) ../systemd-initctl.socket systemd-initctl.socket && \
$(LN_S) ../systemd-shutdownd.socket systemd-shutdownd.socket && \
$(LN_S) ../syslog.socket syslog.socket )
$(LN_S) ../syslog.socket syslog.socket && \
$(LN_S) ../systemd-journald.socket )
( cd $(DESTDIR)$(systemunitdir)/runlevel1.target.wants && \
rm -f systemd-update-utmp-runlevel.service && \
$(LN_S) ../systemd-update-utmp-runlevel.service systemd-update-utmp-runlevel.service )

12
TODO
View file

@ -17,8 +17,20 @@ Bugfixes:
* make polkit checks async
* properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point.
Features:
* logind: selinux is borked...
* logind: sends SessionNew on Lock()?
* logind: allow showing logout dialog from system
* document that %% can be used to write % in a string that is specifier extended
* check utf8 everywhere
* when an instanced service exits, remove its parent cgroup too if possible.
* Make libselinux, libattr, libcap, libdl dependencies only of the tools which actually need them.

View file

@ -149,6 +149,19 @@ if test "x$enable_selinux" != "xno"; then
fi
AM_CONDITIONAL(HAVE_SELINUX, [test "$have_selinux" = "yes"])
have_xz=no
AC_ARG_ENABLE(xz, AS_HELP_STRING([--disable-xz], [Disable optional XZ support]))
if test "x$enable_xz" != "xno"; then
PKG_CHECK_MODULES(XZ, [ liblzma ],
[AC_DEFINE(HAVE_XZ, 1, [Define if XZ is available]) have_xz=yes], have_xz=no)
AC_SUBST(XZ_CFLAGS)
AC_SUBST(XZ_LIBS)
if test "x$have_xz" = xno -a "x$enable_xz" = xyes; then
AC_MSG_ERROR([*** Xz support requested but libraries not found])
fi
fi
AM_CONDITIONAL(HAVE_XZ, [test "$have_xz" = "yes"])
AC_ARG_ENABLE([tcpwrap],
AS_HELP_STRING([--disable-tcpwrap],[Disable optional TCP wrappers support]),
[case "${enableval}" in
@ -591,6 +604,7 @@ AC_MSG_RESULT([
PAM: ${have_pam}
AUDIT: ${have_audit}
SELinux: ${have_selinux}
XZ: ${have_xz}
ACL: ${have_acl}
binfmt: ${have_binfmt}
hostnamed: ${have_hostnamed}

18
libsystemd-id128.pc.in Normal file
View file

@ -0,0 +1,18 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: systemd
Description: systemd 128 Bit ID Utility Library
URL: @PACKAGE_URL@
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lsystemd-id128
Cflags: -I${includedir}

19
libsystemd-journal.pc.in Normal file
View file

@ -0,0 +1,19 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: systemd
Description: systemd Journal Utility Library
URL: @PACKAGE_URL@
Version: @PACKAGE_VERSION@
Requires: libsystemd-id128 = @PACKAGE_VERSION@
Libs: -L${libdir} -lsystemd-journal
Cflags: -I${includedir}

29
man/custom-html.xsl Normal file
View file

@ -0,0 +1,29 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!--
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
<!-- Switch things to UTF-8, ISO-8859-1 is soo yesteryear -->
<xsl:output method="html" encoding="UTF-8" indent="no"/>
</xsl:stylesheet>

View file

@ -50,7 +50,7 @@
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include "sd-daemon.h"</funcsynopsisinfo>
<funcsynopsisinfo>#include &lt;systemd/sd-daemon.h&gt;</funcsynopsisinfo>
</funcsynopsis>
<cmdsynopsis>

146
man/sd-login.xml Normal file
View file

@ -0,0 +1,146 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd-login">
<refentryinfo>
<title>sd-login</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>sd-login</refentrytitle>
<manvolnum>7</manvolnum>
</refmeta>
<refnamediv>
<refname>sd-login</refname>
<refpurpose>APIs for
tracking logins</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-login.h&gt;</funcsynopsisinfo>
</funcsynopsis>
<cmdsynopsis>
<command>pkg-config --cflags --libs libsystemd-login</command>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><filename>sd-login.h</filename> provides APIs to
introspect and monitor seat, login session and user
status information on the local system. </para>
<para>See <ulink
url="http://www.freedesktop.org/wiki/Software/systemd/multiseat">Multi-Seat
on Linux</ulink> for an introduction into multi-seat
support on Linux, the background for this set of APIs.</para>
<para>Note that these APIs only allow purely passive access
and monitoring of seats, sessions and users. To
actively make changes to the seat configuration,
terminate login sessions, or switch session on a seat
you need to utilize the D-Bus API of
systemd-logind, instead.</para>
<para>These functions synchronously access data in
<filename>/proc</filename>,
<filename>/sys/fs/cgroup</filename> and
<filename>/run</filename>. All of these are virtual
file systems, hence the runtime cost of the accesses
is relatively cheap.</para>
<para>It is possible (and often a very good choice) to
mix calls to the synchronous interface of
<filename>sd-login.h</filename> with the asynchronous
D-Bus interface of systemd-logind. However, if this is
done you need to think a bit about possible races
since the stream of events from D-Bus and from
<filename>sd-login.h</filename> interfaces such as the
login monitor are asynchronous and not ordered against
each other.</para>
<para>If the functions return string arrays, these are
generally NULL terminated and need to be freed by the
caller with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use, including the strings referenced
therein. Similar, individual strings returned need to
be freed, as well.</para>
<para>As a special exception, instead of an empty
string array NULL may be returned, which should be
treated equivalent to an empty string array.</para>
<para>See
<citerefentry><refentrytitle>sd_pid_get_session</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_uid_get_state</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_session_is_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_seat_get_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_get_seats</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_login_monitor_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for more information about the functions
implemented.</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>These APIs are implemented as shared library,
which can be compiled and linked to with the
<literal>libsystemd-login</literal>
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_pid_get_session</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_uid_get_state</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_session_is_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_seat_get_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_get_seats</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_login_monitor_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-readahead</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -49,7 +49,7 @@
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include "sd-daemon.h"</funcsynopsisinfo>
<funcsynopsisinfo>#include &lt;systemd/sd-daemon.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_booted</function></funcdef>

127
man/sd_get_seats.xml Normal file
View file

@ -0,0 +1,127 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_get_seats">
<refentryinfo>
<title>sd_get_seats</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>sd_get_seats</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_get_seats</refname>
<refname>sd_get_sessions</refname>
<refname>sd_get_uids</refname>
<refpurpose>Determine available seats, sessions and logged in users</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-login.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_get_seats</function></funcdef>
<paramdef>char*** <parameter>seats</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_get_sessions</function></funcdef>
<paramdef>char*** <parameter>sessions</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_get_uids</function></funcdef>
<paramdef>char*** <parameter>sessions</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_get_seats()</function> may be used
to determine all currently available local
seats. Returns a NULL terminated array of seat
identifiers. The returned array and all strings it
references need to be freed with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use. Note that instead of an empty array
NULL may be returned and should be considered
equivalent to an empty array.</para>
<para>Similar, <function>sd_get_sessions()</function> may
be used to determine all current login sessions.</para>
<para>Similar, <function>sd_get_uids()</function> may
be used to determine all Unix users who currently have login sessions.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success <function>sd_get_seats()</function>,
<function>sd_get_sessions()</function> and
<function>sd_get_uids()</function> return the number
of entries in the arrays. On failure, these calls
return a negative errno-style error code.</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>The <function>sd_get_seats()</function>,
<function>sd_get_sessions()</function> and
<function>sd_get_uids()</function> interfaces
are available as shared library, which can be compiled
and linked to with the
<literal>libsystemd-login</literal>
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_session_get_seat</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -53,7 +53,7 @@
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include "sd-daemon.h"</funcsynopsisinfo>
<funcsynopsisinfo>#include &lt;systemd/sd-daemon.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_is_fifo</function></funcdef>

View file

@ -49,7 +49,7 @@
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include "sd-daemon.h"</funcsynopsisinfo>
<funcsynopsisinfo>#include &lt;systemd/sd-daemon.h&gt;</funcsynopsisinfo>
<funcsynopsisinfo>#define SD_LISTEN_FDS_START 3</funcsynopsisinfo>

View file

@ -0,0 +1,172 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_login_monitor_new">
<refentryinfo>
<title>sd_login_monitor_new</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>sd_login_monitor_new</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_login_monitor_new</refname>
<refname>sd_login_monitor_unref</refname>
<refname>sd_login_monitor_flush</refname>
<refname>sd_login_monitor_get_fd</refname>
<refpurpose>Monitor login sessions, seats and users</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-login.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_login_monitor_new</function></funcdef>
<paramdef>const char* <parameter>category</parameter></paramdef>
<paramdef>sd_login_monitor** <parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>sd_login_monitor* <function>sd_login_monitor_unref</function></funcdef>
<paramdef>sd_login_monitor* <parameter>m</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_login_monitor_flush</function></funcdef>
<paramdef>sd_login_monitor* <parameter>m</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_login_monitor_get_fd</function></funcdef>
<paramdef>sd_login_monitor* <parameter>m</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_login_monitor_new()</function> may
be used to monitor login session, users and seats. Via
a monitor object a file descriptor can be integrated
into an application defined event loop which is woken
up each time a user logs in, logs out or a seat is
added or removed, or a session, user, or seat changes
state otherwise. The first parameter takes a string
which can be either <literal>seat</literal> (to get
only notifications about seats being added, removed or
changed), <literal>session</literal> (to get only
notifications about sessions being created or removed
or changed) or <literal>uid</literal> (to get only
notifications when a user changes state in respect to
logins). If notifications shall be generated in all
these conditions, NULL may be passed. Note that in
future additional categories may be defined. The
second parameter returns a monitor object and needs to
be freed with the
<function>sd_login_monitor_unref()</function> call
after use.</para>
<para><function>sd_login_monitor_unref()</function>
may be used to destroy a monitor object. Note that
this will invalidate any file descriptor returned by
<function>sd_login_monitor_get_fd()</function>.</para>
<para><function>sd_login_monitor_flush()</function>
may be used to reset the wakeup state of the monitor
object. Whenever an event causes the monitor to wake
up the event loop via the file descriptor this
function needs to be called to reset the wake-up
state. If this call is not invoked the file descriptor
will immediately wake up the event loop again.</para>
<para><function>sd_login_monitor_get_fd()</function>
may be used to retrieve the file descriptor of the
monitor object that may be integrated in an
application defined event loop, based around
<citerefentry><refentrytitle>poll</refentrytitle><manvolnum>2</manvolnum></citerefentry>
or a similar interface. The application should include
the returned file descriptor as wake up source for
POLLIN events. Whenever a wake-up is triggered the
file descriptor needs to be reset via
<function>sd_login_monitor_flush()</function>. An
application needs to reread the login state with a
function like
<citerefentry><refentrytitle>sd_get_seats</refentrytitle><manvolnum>3</manvolnum></citerefentry>
or similar to determine what changed.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success
<function>sd_login_monitor_new()</function> and
<function>sd_login_monitor_flush()</function> return 0
or a positive integer. On success
<function>sd_login_monitor_get_fd()</function> returns
a Unix file descriptor. On failure, these calls return
a negative errno-style error code.</para>
<para><function>sd_login_monitor_unref()</function>
always returns NULL.</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>The <function>sd_login_monitor_new()</function>,
<function>sd_login_monitor_unref()</function>, <function>sd_login_monitor_flush()</function> and
<function>sd_login_monitor_get_fd()</function> interfaces
are available as shared library, which can be compiled
and linked to with the
<literal>libsystemd-login</literal>
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_get_seats</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -50,7 +50,7 @@
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include "sd-daemon.h"</funcsynopsisinfo>
<funcsynopsisinfo>#include &lt;systemd/sd-daemon.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_notify</function></funcdef>

135
man/sd_pid_get_session.xml Normal file
View file

@ -0,0 +1,135 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_pid_get_session">
<refentryinfo>
<title>sd_pid_get_session</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>sd_pid_get_session</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_pid_get_session</refname>
<refname>sd_pid_get_owner_uid</refname>
<refpurpose>Determine session or owner of a session of a specific PID</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-login.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_pid_get_session</function></funcdef>
<paramdef>pid_t <parameter>pid</parameter></paramdef>
<paramdef>char** <parameter>session</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_pid_get_owner_uid</function></funcdef>
<paramdef>pid_t <parameter>pid</parameter></paramdef>
<paramdef>uid_t* <parameter>uid</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_pid_get_session()</function> may be
used to determine the login session identifier of a
process identified by the specified process
identifier. The session identifier is a short string,
suitable for usage in file system paths. Note that not
all processes are part of a login session (e.g. system
service processes and user processes that are shared
between multiple sessions of the same user). For
processes not being part of a login session this
function will fail. The returned string needs to be
freed with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
<para><function>sd_pid_get_owner_uid()</function> may
be used to determine the Unix user identifier of the
owner of the session of a process identified the
specified PID. Note that this function will succeed
for user processes which are shared between multiple
login sessions of the same user, where
<function>sd_pid_get_session()</function> will
fail. For processes not being part of a login session
and not being a shared process of a user this function
will fail.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success these calls return 0 or a positive
integer. On failure, these calls return a negative
errno-style error code.</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>The <function>sd_pid_get_session()</function>
and <function>sd_pid_get_owner_uid()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
<literal>libsystemd-login</literal>
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
<para>Note that the login session identifier as
returned by <function>sd_pid_get_session()</function>
is completely unrelated to the process session
identifier as returned by
<citerefentry><refentrytitle>getsid</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_session_is_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>getsid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -49,7 +49,7 @@
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include "sd-daemon.h"</funcsynopsisinfo>
<funcsynopsisinfo>#include "sd-readahead.h"</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_readahead</function></funcdef>
@ -134,23 +134,17 @@
url="http://cgit.freedesktop.org/systemd/tree/src/sd-readahead.h"/></para>
<para><function>sd_readahead()</function> is
implemented in the reference implementation's
implemented in the reference implementation's drop-in
<filename>sd-readahead.c</filename> and
<filename>sd-readahead.h</filename> files. These
interfaces are available as shared library, which can
be compiled and linked to with the
<literal>libsystemd-daemon</literal>
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file. Alternatively, applications consuming this API
may copy the implementation into their source
tree. For more details about the reference
implementation see
<citerefentry><refentrytitle>sd-readahead</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
<filename>sd-readahead.h</filename> files. It is
recommended that applications consuming this API copy
the implementation into their source tree. For more
details about the reference implementation see
<citerefentry><refentrytitle>sd-readahead</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
<para>If the reference implementation is used as
drop-in files and -DDISABLE_SYSTEMD is set during
compilation this function will always return 0 and
otherwise become a NOP.</para>
<para>If -DDISABLE_SYSTEMD is set during compilation
this function will always return 0 and otherwise
become a NOP.</para>
</refsect1>
<refsect1>

152
man/sd_seat_get_active.xml Normal file
View file

@ -0,0 +1,152 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_seat_get_active">
<refentryinfo>
<title>sd_seat_get_active</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>sd_seat_get_active</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_seat_get_active</refname>
<refname>sd_seat_get_sessions</refname>
<refname>sd_seat_can_multi_session</refname>
<refpurpose>Determine state of a specific seat</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-login.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_seat_get_active</function></funcdef>
<paramdef>const char* <parameter>seat</parameter></paramdef>
<paramdef>char** <parameter>session</parameter></paramdef>
<paramdef>uid_t* <parameter>uid</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_seat_get_sessions</function></funcdef>
<paramdef>const char* <parameter>seat</parameter></paramdef>
<paramdef>char*** <parameter>sessions</parameter></paramdef>
<paramdef>uid_t** <parameter>uid</parameter></paramdef>
<paramdef>unsigned* <parameter>n_uids</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_seat_can_multi_session</function></funcdef>
<paramdef>const char* <parameter>session</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_seat_get_active()</function> may be
used to determine which session is currently active on
a seat, if there is any. Returns the session
identifier and the user identifier of the Unix user
the session is belonging to. Either the session or the
user identifier parameter can be be passed NULL, in
case only one of the parameters shall be queried. The
returned string needs to be freed with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
<para><function>sd_seat_get_sessions()</function> may
be used to determine all sessions on the specified
seat. Returns two arrays, one (NULL terminated) with
the session identifiers of the sessions and one with
the user identifiers of the Unix users the sessions
belong to. An additional parameter may be used to
return the number of entries in the latter array. The
two arrays and the latter parameter may be passed as
NULL in case these values need not to be
determined. The arrays and the strings referenced by
them need to be freed with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use. Note that instead of an empty array
NULL may be returned and should be considered
equivalent to an empty array.</para>
<para><function>sd_seat_can_multi_session()</function>
may be used to determine whether a specific seat is
capable of multi-session, i.e. allows multiple login
sessions in parallel (whith only one being active at a
time).</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para> On success
<function>sd_seat_get_active()</function> return
return 0 or a positive integer. On success
<function>sd_seat_get_sessions()</function> returns
the number of entries in the session identifier
array. If the test succeeds
<function>sd_seat_can_multi_session</function> returns
a positive integer, if it fails 0. On failure, these
calls return a negative errno-style error code.</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>The <function>sd_seat_get_active()</function>,
<function>sd_seat_get_sessions()</function>, and
<function>sd_seat_can_multi_session()</function> interfaces
are available as shared library, which can be compiled
and linked to with the
<literal>libsystemd-login</literal>
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_session_get_seat</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,134 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_session_is_active">
<refentryinfo>
<title>sd_session_is_active</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>sd_session_is_active</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_session_is_active</refname>
<refname>sd_session_get_uid</refname>
<refname>sd_session_get_seat</refname>
<refpurpose>Determine state of a specific session</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-login.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_session_is_active</function></funcdef>
<paramdef>const char* <parameter>session</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_session_get_uid</function></funcdef>
<paramdef>const char* <parameter>session</parameter></paramdef>
<paramdef>uid_t* <parameter>uid</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_session_get_seat</function></funcdef>
<paramdef>const char* <parameter>session</parameter></paramdef>
<paramdef>char** <parameter>seat</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_session_is_active()</function> may
be used to determine whether the session identified by
the specified session identifier is currently active
(i.e. currently in the foreground and available for
user input) or not.</para>
<para><function>sd_session_get_uid()</function> may be
used to determine the user identifier of the Unix user the session
identified by the specified session identifier belongs
to.</para>
<para><function>sd_session_get_seat()</function> may
be used to determine the seat identifier of the seat
the session identified by the specified session
identifier belongs to. Note that not all sessions are
attached to a seat, this call will fail for them. The
returned string needs to be freed with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>If the test succeeds
<function>sd_session_is_active()</function> returns a
positive integer, if it fails 0. On success
<function>sd_session_get_uid()</function> and
<function>sd_session_get_seat()</function> return 0 or
a positive integer. On failure, these calls return a
negative errno-style error code.</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>The <function>sd_session_is_active()</function>,
<function>sd_session_get_uid()</function>, and
<function>sd_session_get_seat()</function> interfaces
are available as shared library, which can be compiled
and linked to with the
<literal>libsystemd-login</literal>
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_pid_get_session</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

185
man/sd_uid_get_state.xml Normal file
View file

@ -0,0 +1,185 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_uid_get_state">
<refentryinfo>
<title>sd_uid_get_state</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>sd_uid_get_state</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_uid_get_state</refname>
<refname>sd_uid_is_on_seat</refname>
<refname>sd_uid_get_sessions</refname>
<refname>sd_uid_get_seats</refname>
<refpurpose>Determine login state of a specific Unix user ID</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-login.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_uid_get_state</function></funcdef>
<paramdef>uid_t <parameter>pid</parameter></paramdef>
<paramdef>char** <parameter>state</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_uid_is_on_seat</function></funcdef>
<paramdef>uid_t <parameter>pid</parameter></paramdef>
<paramdef>int <parameter>require_active</parameter></paramdef>
<paramdef>const char* <parameter>seat</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_uid_get_sessions</function></funcdef>
<paramdef>uid_t <parameter>pid</parameter></paramdef>
<paramdef>int <parameter>require_active</parameter></paramdef>
<paramdef>char*** <parameter>sessions</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_uid_get_seats</function></funcdef>
<paramdef>uid_t <parameter>pid</parameter></paramdef>
<paramdef>int <parameter>require_active</parameter></paramdef>
<paramdef>char*** <parameter>seats</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_uid_get_state()</function> may be
used to determine the login state of a specific Unix
user identifier. The following states are currently
known: <literal>offline</literal> (user not logged in
at all), <literal>lingering</literal> (user not logged
in, but some user services running),
<literal>online</literal> (user logged in, but not
active), <literal>active</literal> (user logged in on
an active seat). In the future additional states might
be defined, client code should be written to be robust
in regards to additional state strings being
returned. The returned string needs to be freed with
the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
<para><function>sd_uid_is_on_seat()</function> may be
used to determine whether a specific user is logged in
or active on a specific seat. Accepts a Unix user
identifier and a seat identifier string as
parameters. The <parameter>require_active</parameter>
parameter is a boolean. If non-zero (true) this
function will test if the user is active (i.e. has a
session that is in the foreground and accepting user
input) on the specified seat, otherwise (false) only
if the user is logged in (and possibly inactive) on
the specified seat.</para>
<para><function>sd_uid_get_sessions()</function> may
be used to determine the current sessions of the
specified user. Acceptes a Unix user identifier as
parameter. The <parameter>require_active</parameter>
boolean parameter controls whether the returned list
shall consist of only those sessions where the user is
currently active (true) or where the user is currently
logged in at all, possibly inactive (false). The call
returns a NULL terminated string array of session
identifiers in <parameter>sessions</parameter> which
needs to be freed by the caller with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use, including all the strings
referenced. If the string array parameter is passed as
NULL the array will not be filled in, but the return
code still indicates the number of current
sessions. Note that instead of an empty array NULL may
be returned and should be considered equivalent to an
empty array.</para>
<para>Similar, <function>sd_uid_get_seats()</function>
may be used to determine the list of seats on which
the user currently has sessions. Similar semantics
apply, however note that the user may have
multiple sessions on the same seat as well as sessions
with no attached seat and hence the number of entries
in the returned array may differ from the one returned
by <function>sd_uid_get_sessions()</function>.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success
<function>sd_uid_get_state()</function> returns 0 or a
positive integer. If the test succeeds
<function>sd_uid_is_on_seat()</function> returns a
positive integer, if it fails
0. <function>sd_uid_get_sessions()</function> and
<function>sd_uid_get_seats()</function> return the
number of entries in the returned arrays. On failure,
these calls return a negative errno-style error
code.</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>The <function>sd_uid_get_state()</function>,
<function>sd_uid_is_on_seat()</function>,
<function>sd_uid_get_sessions()</function>, and
<function>sd_uid_get_seats()</function> interfaces are
available as shared library, which can be compiled and
linked to with the <literal>libsystemd-login</literal>
<citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_pid_get_owner_uid</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

1
po/.gitignore vendored
View file

@ -1,3 +1,4 @@
POTFILES
Makefile.in.in
.intltool-merge-cache
Makefile

View file

@ -44,7 +44,7 @@ SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:
# Apply sysctl variables to network devices (and only to those) as they appear.
SUBSYSTEM=="net", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/proc/sys/net/ipv4/conf/$name --prefix=/proc/sys/net/ipv4/neigh/$name --prefix=/proc/sys/net/ipv6/conf/$name --prefix=/proc/sys/net/ipv6/neigh/$name"
SUBSYSTEM=="net", KERNEL!="lo", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/proc/sys/net/ipv4/conf/$name --prefix=/proc/sys/net/ipv4/neigh/$name --prefix=/proc/sys/net/ipv6/conf/$name --prefix=/proc/sys/net/ipv6/neigh/$name"
# Asynchronously mount file systems implemented by these modules as
# soon as they are loaded.

68
src/acl-util.c Normal file
View file

@ -0,0 +1,68 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <assert.h>
#include <sys/acl.h>
#include <acl/libacl.h>
#include <errno.h>
#include <stdbool.h>
#include "acl-util.h"
int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
acl_entry_t i;
int found;
assert(acl);
assert(entry);
for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
found > 0;
found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
acl_tag_t tag;
uid_t *u;
bool b;
if (acl_get_tag_type(i, &tag) < 0)
return -errno;
if (tag != ACL_USER)
continue;
u = acl_get_qualifier(i);
if (!u)
return -errno;
b = *u == uid;
acl_free(u);
if (b) {
*entry = i;
return 1;
}
}
if (found < 0)
return -errno;
return 0;
}

27
src/acl-util.h Normal file
View file

@ -0,0 +1,27 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef fooaclutilhfoo
#define fooaclutilhfoo
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
#endif

View file

@ -770,7 +770,7 @@ static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
if (packet.v5_packet.pid > 0) {
char *p = NULL;
get_process_name(packet.v5_packet.pid, &p);
get_process_comm(packet.v5_packet.pid, &p);
log_debug("Got direct mount request for %s, triggered by %lu (%s)", packet.v5_packet.name, (unsigned long) packet.v5_packet.pid, strna(p));
free(p);

View file

@ -133,7 +133,7 @@ static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigne
for (i = 0; i < n; i++) {
char *t = NULL;
get_process_cmdline(pids[i], n_columns, &t);
get_process_cmdline(pids[i], n_columns, true, &t);
printf("%s%s %*lu %s\n",
prefix,

View file

@ -558,6 +558,17 @@ void* hashmap_first(Hashmap *h) {
return h->iterate_list_head->value;
}
void* hashmap_first_key(Hashmap *h) {
if (!h)
return NULL;
if (!h->iterate_list_head)
return NULL;
return (void*) h->iterate_list_head->key;
}
void* hashmap_last(Hashmap *h) {
if (!h)

View file

@ -74,6 +74,7 @@ void hashmap_clear(Hashmap *h);
void *hashmap_steal_first(Hashmap *h);
void *hashmap_steal_first_key(Hashmap *h);
void* hashmap_first(Hashmap *h);
void* hashmap_first_key(Hashmap *h);
void* hashmap_last(Hashmap *h);
char **hashmap_get_strv(Hashmap *h);

1
src/journal/Makefile Symbolic link
View file

@ -0,0 +1 @@
../Makefile

208
src/journal/compress.c Normal file
View file

@ -0,0 +1,208 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <lzma.h>
#include "compress.h"
bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size) {
lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret;
bool b = false;
assert(src);
assert(src_size > 0);
assert(dst);
assert(dst_size);
/* Returns false if we couldn't compress the data or the
* compressed result is longer than the original */
ret = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_NONE);
if (ret != LZMA_OK)
return false;
s.next_in = src;
s.avail_in = src_size;
s.next_out = dst;
s.avail_out = src_size;
/* Does it fit? */
if (lzma_code(&s, LZMA_FINISH) != LZMA_STREAM_END)
goto fail;
/* Is it actually shorter? */
if (s.avail_out == 0)
goto fail;
*dst_size = src_size - s.avail_out;
b = true;
fail:
lzma_end(&s);
return b;
}
bool uncompress_blob(const void *src, uint64_t src_size,
void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size) {
lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret;
bool b = false;
assert(src);
assert(src_size > 0);
assert(dst);
assert(dst_alloc_size);
assert(dst_size);
assert(*dst_alloc_size == 0 || *dst);
ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
if (ret != LZMA_OK)
return false;
if (*dst_alloc_size <= src_size) {
void *p;
p = realloc(*dst, src_size*2);
if (!p)
return false;
*dst = p;
*dst_alloc_size = src_size*2;
}
s.next_in = src;
s.avail_in = src_size;
s.next_out = *dst;
s.avail_out = *dst_alloc_size;
for (;;) {
void *p;
ret = lzma_code(&s, LZMA_FINISH);
if (ret == LZMA_STREAM_END)
break;
if (ret != LZMA_OK)
goto fail;
p = realloc(*dst, *dst_alloc_size*2);
if (!p)
goto fail;
s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *dst);
s.avail_out += *dst_alloc_size;
*dst = p;
*dst_alloc_size *= 2;
}
*dst_size = *dst_alloc_size - s.avail_out;
b = true;
fail:
lzma_end(&s);
return b;
}
bool uncompress_startswith(const void *src, uint64_t src_size,
void **buffer, uint64_t *buffer_size,
const void *prefix, uint64_t prefix_len,
uint8_t extra) {
lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret;
bool b = false;
/* Checks whether the uncompressed blob starts with the
* mentioned prefix. The byte extra needs to follow the
* prefix */
assert(src);
assert(src_size > 0);
assert(buffer);
assert(buffer_size);
assert(prefix);
assert(*buffer_size == 0 || *buffer);
ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
if (ret != LZMA_OK)
return false;
if (*buffer_size <= prefix_len) {
void *p;
p = realloc(*buffer, prefix_len*2);
if (!p)
return false;
*buffer = p;
*buffer_size = prefix_len*2;
}
s.next_in = src;
s.avail_in = src_size;
s.next_out = *buffer;
s.avail_out = *buffer_size;
for (;;) {
void *p;
ret = lzma_code(&s, LZMA_FINISH);
if (ret != LZMA_STREAM_END && ret != LZMA_OK)
goto fail;
if ((*buffer_size - s.avail_out > prefix_len) &&
memcmp(*buffer, prefix, prefix_len) == 0 &&
((const uint8_t*) *buffer)[prefix_len] == extra)
break;
if (ret == LZMA_STREAM_END)
goto fail;
p = realloc(*buffer, *buffer_size*2);
if (!p)
goto fail;
s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *buffer);
s.avail_out += *buffer_size;
*buffer = p;
*buffer_size *= 2;
}
b = true;
fail:
lzma_end(&s);
return b;
}

38
src/journal/compress.h Normal file
View file

@ -0,0 +1,38 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foocompresshfoo
#define foocompresshfoo
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <inttypes.h>
#include <stdbool.h>
bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size);
bool uncompress_blob(const void *src, uint64_t src_size,
void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size);
bool uncompress_startswith(const void *src, uint64_t src_size,
void **buffer, uint64_t *buffer_size,
const void *prefix, uint64_t prefix_len,
uint8_t extra);
#endif

164
src/journal/journal-def.h Normal file
View file

@ -0,0 +1,164 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foojournaldefhfoo
#define foojournaldefhfoo
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <inttypes.h>
#include "macro.h"
#include "sd-id128.h"
typedef struct Header Header;
typedef struct ObjectHeader ObjectHeader;
typedef union Object Object;
typedef struct DataObject DataObject;
typedef struct FieldObject FieldObject;
typedef struct EntryObject EntryObject;
typedef struct HashTableObject HashTableObject;
typedef struct EntryArrayObject EntryArrayObject;
typedef struct EntryItem EntryItem;
typedef struct HashItem HashItem;
/* Object types */
enum {
OBJECT_UNUSED,
OBJECT_DATA,
OBJECT_FIELD,
OBJECT_ENTRY,
OBJECT_DATA_HASH_TABLE,
OBJECT_FIELD_HASH_TABLE,
OBJECT_ENTRY_ARRAY,
_OBJECT_TYPE_MAX
};
/* Object flags */
enum {
OBJECT_COMPRESSED = 1
};
_packed_ struct ObjectHeader {
uint8_t type;
uint8_t flags;
uint8_t reserved[6];
uint64_t size;
uint8_t payload[];
};
_packed_ struct DataObject {
ObjectHeader object;
uint64_t hash;
uint64_t next_hash_offset;
uint64_t next_field_offset;
uint64_t entry_offset; /* the first array entry we store inline */
uint64_t entry_array_offset;
uint64_t n_entries;
uint8_t payload[];
};
_packed_ struct FieldObject {
ObjectHeader object;
uint64_t hash;
uint64_t next_hash_offset;
uint64_t head_data_offset;
uint64_t tail_data_offset;
uint8_t payload[];
};
_packed_ struct EntryItem {
uint64_t object_offset;
uint64_t hash;
};
_packed_ struct EntryObject {
ObjectHeader object;
uint64_t seqnum;
uint64_t realtime;
uint64_t monotonic;
sd_id128_t boot_id;
uint64_t xor_hash;
EntryItem items[];
};
_packed_ struct HashItem {
uint64_t head_hash_offset;
uint64_t tail_hash_offset;
};
_packed_ struct HashTableObject {
ObjectHeader object;
HashItem items[];
};
_packed_ struct EntryArrayObject {
ObjectHeader object;
uint64_t next_entry_array_offset;
uint64_t items[];
};
union Object {
ObjectHeader object;
DataObject data;
FieldObject field;
EntryObject entry;
HashTableObject hash_table;
EntryArrayObject entry_array;
};
enum {
STATE_OFFLINE,
STATE_ONLINE,
STATE_ARCHIVED
};
/* Header flags */
enum {
HEADER_INCOMPATIBLE_COMPRESSED = 1
};
_packed_ struct Header {
uint8_t signature[8]; /* "LPKSHHRH" */
uint32_t compatible_flags;
uint32_t incompatible_flags;
uint8_t state;
uint8_t reserved[7];
sd_id128_t file_id;
sd_id128_t machine_id;
sd_id128_t boot_id;
sd_id128_t seqnum_id;
uint64_t arena_offset;
uint64_t arena_size;
uint64_t data_hash_table_offset; /* for looking up data objects */
uint64_t data_hash_table_size;
uint64_t field_hash_table_offset; /* for looking up field objects */
uint64_t field_hash_table_size;
uint64_t tail_object_offset;
uint64_t n_objects;
uint64_t n_entries;
uint64_t seqnum;
uint64_t first_seqnum;
uint64_t entry_array_offset;
uint64_t head_entry_realtime;
uint64_t tail_entry_realtime;
uint64_t tail_entry_monotonic;
};
#endif

2078
src/journal/journal-file.c Normal file

File diff suppressed because it is too large Load diff

127
src/journal/journal-file.h Normal file
View file

@ -0,0 +1,127 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foojournalfilehfoo
#define foojournalfilehfoo
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <inttypes.h>
#include "journal-def.h"
#include "util.h"
#include "sd-id128.h"
#define DEFAULT_MAX_SIZE (128ULL*1024ULL*1024ULL)
#define DEFAULT_MIN_SIZE (256ULL*1024ULL)
#define DEFAULT_KEEP_FREE (1ULL*1024ULL*1024ULL)
#define DEFAULT_MAX_USE (16ULL*1024ULL*1024ULL*16ULL)
typedef struct Window {
void *ptr;
uint64_t offset;
uint64_t size;
} Window;
enum {
WINDOW_UNKNOWN = OBJECT_UNUSED,
WINDOW_DATA = OBJECT_DATA,
WINDOW_ENTRY = OBJECT_ENTRY,
WINDOW_DATA_HASH_TABLE = OBJECT_DATA_HASH_TABLE,
WINDOW_FIELD_HASH_TABLE = OBJECT_FIELD_HASH_TABLE,
WINDOW_ENTRY_ARRAY = OBJECT_ENTRY_ARRAY,
WINDOW_HEADER,
_WINDOW_MAX
};
typedef struct JournalMetrics {
uint64_t max_size;
uint64_t min_size;
uint64_t keep_free;
uint64_t max_use;
} JournalMetrics;
typedef struct JournalFile {
int fd;
char *path;
struct stat last_stat;
mode_t mode;
int flags;
int prot;
bool writable;
bool tail_entry_monotonic_valid;
Header *header;
HashItem *data_hash_table;
HashItem *field_hash_table;
Window windows[_WINDOW_MAX];
uint64_t current_offset;
JournalMetrics metrics;
bool compress;
#ifdef HAVE_XZ
void *compress_buffer;
size_t compress_buffer_size;
#endif
} JournalFile;
typedef enum direction {
DIRECTION_UP,
DIRECTION_DOWN
} direction_t;
int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile *template, JournalFile **ret);
void journal_file_close(JournalFile *j);
int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret);
uint64_t journal_file_entry_n_items(Object *o);
int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset);
int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset);
int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset);
int journal_file_next_entry(JournalFile *f, Object *o, uint64_t p, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_skip_entry(JournalFile *f, Object *o, uint64_t p, int64_t skip, Object **ret, uint64_t *offset);
int journal_file_next_entry_for_data(JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_offset, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset);
void journal_file_dump(JournalFile *f);
int journal_file_rotate(JournalFile **f);
int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free);
void journal_file_post_change(JournalFile *f);
#endif

View file

@ -0,0 +1,83 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foojournalinternalhfoo
#define foojournalinternalhfoo
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/types.h>
#include <inttypes.h>
#include <stdbool.h>
#include "list.h"
#include "sd-id128.h"
typedef struct Match Match;
struct Match {
char *data;
size_t size;
uint64_t le_hash;
LIST_FIELDS(Match, matches);
};
typedef enum location_type {
LOCATION_HEAD,
LOCATION_TAIL,
LOCATION_DISCRETE
} location_type_t;
typedef struct Location {
location_type_t type;
uint64_t seqnum;
sd_id128_t seqnum_id;
bool seqnum_set;
uint64_t realtime;
bool realtime_set;
uint64_t monotonic;
sd_id128_t boot_id;
bool monotonic_set;
uint64_t xor_hash;
bool xor_hash_set;
} Location;
struct sd_journal {
int flags;
Hashmap *files;
Location current_location;
JournalFile *current_file;
uint64_t current_field;
int inotify_fd;
Hashmap *inotify_wd_dirs;
Hashmap *inotify_wd_roots;
LIST_HEAD(Match, matches);
unsigned n_matches;
};
#endif

View file

@ -0,0 +1,275 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <string.h>
#include <errno.h>
#include "journal-rate-limit.h"
#include "list.h"
#include "util.h"
#include "hashmap.h"
#define POOLS_MAX 5
#define BUCKETS_MAX 127
#define GROUPS_MAX 2047
static const int priority_map[] = {
[LOG_EMERG] = 0,
[LOG_ALERT] = 0,
[LOG_CRIT] = 0,
[LOG_ERR] = 1,
[LOG_WARNING] = 2,
[LOG_NOTICE] = 3,
[LOG_INFO] = 3,
[LOG_DEBUG] = 4
};
typedef struct JournalRateLimitPool JournalRateLimitPool;
typedef struct JournalRateLimitGroup JournalRateLimitGroup;
struct JournalRateLimitPool {
usec_t begin;
unsigned num;
unsigned suppressed;
};
struct JournalRateLimitGroup {
JournalRateLimit *parent;
char *id;
JournalRateLimitPool pools[POOLS_MAX];
unsigned hash;
LIST_FIELDS(JournalRateLimitGroup, bucket);
LIST_FIELDS(JournalRateLimitGroup, lru);
};
struct JournalRateLimit {
usec_t interval;
unsigned burst;
JournalRateLimitGroup* buckets[BUCKETS_MAX];
JournalRateLimitGroup *lru, *lru_tail;
unsigned n_groups;
};
JournalRateLimit *journal_rate_limit_new(usec_t interval, unsigned burst) {
JournalRateLimit *r;
assert(interval > 0 || burst == 0);
r = new0(JournalRateLimit, 1);
if (!r)
return NULL;
r->interval = interval;
r->burst = burst;
return r;
}
static void journal_rate_limit_group_free(JournalRateLimitGroup *g) {
assert(g);
if (g->parent) {
assert(g->parent->n_groups > 0);
if (g->parent->lru_tail == g)
g->parent->lru_tail = g->lru_prev;
LIST_REMOVE(JournalRateLimitGroup, lru, g->parent->lru, g);
LIST_REMOVE(JournalRateLimitGroup, bucket, g->parent->buckets[g->hash % BUCKETS_MAX], g);
g->parent->n_groups --;
}
free(g->id);
free(g);
}
void journal_rate_limit_free(JournalRateLimit *r) {
assert(r);
while (r->lru)
journal_rate_limit_group_free(r->lru);
free(r);
}
static bool journal_rate_limit_group_expired(JournalRateLimitGroup *g, usec_t ts) {
unsigned i;
assert(g);
for (i = 0; i < POOLS_MAX; i++)
if (g->pools[i].begin + g->parent->interval >= ts)
return false;
return true;
}
static void journal_rate_limit_vacuum(JournalRateLimit *r, usec_t ts) {
assert(r);
/* Makes room for at least one new item, but drop all
* expored items too. */
while (r->n_groups >= GROUPS_MAX ||
(r->lru_tail && journal_rate_limit_group_expired(r->lru_tail, ts)))
journal_rate_limit_group_free(r->lru_tail);
}
static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r, const char *id, usec_t ts) {
JournalRateLimitGroup *g;
assert(r);
assert(id);
g = new0(JournalRateLimitGroup, 1);
if (!g)
return NULL;
g->id = strdup(id);
if (!g->id)
goto fail;
g->hash = string_hash_func(g->id);
journal_rate_limit_vacuum(r, ts);
LIST_PREPEND(JournalRateLimitGroup, bucket, r->buckets[g->hash % BUCKETS_MAX], g);
LIST_PREPEND(JournalRateLimitGroup, lru, r->lru, g);
if (!g->lru_next)
r->lru_tail = g;
r->n_groups ++;
g->parent = r;
return g;
fail:
journal_rate_limit_group_free(g);
return NULL;
}
static uint64_t u64log2(uint64_t n) {
unsigned r;
if (n <= 1)
return 0;
r = 0;
for (;;) {
n = n >> 1;
if (!n)
return r;
r++;
}
}
static unsigned burst_modulate(unsigned burst, uint64_t available) {
unsigned k;
/* Modulates the burst rate a bit with the amount of available
* disk space */
k = u64log2(available);
/* 1MB */
if (k <= 20)
return burst;
burst = (burst * (k-20)) / 4;
/*
* Example:
*
* <= 1MB = rate * 1
* 16MB = rate * 2
* 256MB = rate * 3
* 4GB = rate * 4
* 64GB = rate * 5
* 1TB = rate * 6
*/
return burst;
}
int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available) {
unsigned h;
JournalRateLimitGroup *g;
JournalRateLimitPool *p;
unsigned burst;
usec_t ts;
assert(id);
if (!r)
return 1;
if (r->interval == 0 || r->burst == 0)
return 1;
burst = burst_modulate(r->burst, available);
ts = now(CLOCK_MONOTONIC);
h = string_hash_func(id);
g = r->buckets[h % BUCKETS_MAX];
LIST_FOREACH(bucket, g, g)
if (streq(g->id, id))
break;
if (!g) {
g = journal_rate_limit_group_new(r, id, ts);
if (!g)
return -ENOMEM;
}
p = &g->pools[priority_map[priority]];
if (p->begin <= 0) {
p->suppressed = 0;
p->num = 1;
p->begin = ts;
return 1;
}
if (p->begin + r->interval < ts) {
unsigned s;
s = p->suppressed;
p->suppressed = 0;
p->num = 1;
p->begin = ts;
return 1 + s;
}
if (p->num <= burst) {
p->num++;
return 1;
}
p->suppressed++;
return 0;
}

View file

@ -0,0 +1,34 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foojournalratelimithfoo
#define foojournalratelimithfoo
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "macro.h"
#include "util.h"
typedef struct JournalRateLimit JournalRateLimit;
JournalRateLimit *journal_rate_limit_new(usec_t interval, unsigned burst);
void journal_rate_limit_free(JournalRateLimit *r);
int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available);
#endif

259
src/journal/journal-send.c Normal file
View file

@ -0,0 +1,259 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <stddef.h>
#include "sd-journal.h"
#include "util.h"
#include "socket-util.h"
/* We open a single fd, and we'll share it with the current process,
* all its threads, and all its subprocesses. This means we need to
* initialize it atomically, and need to operate on it atomically
* never assuming we are the only user */
static int journal_fd(void) {
int fd;
static int fd_plus_one = 0;
retry:
if (fd_plus_one > 0)
return fd_plus_one - 1;
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
if (fd < 0)
return -errno;
if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
close_nointr_nofail(fd);
goto retry;
}
return fd;
}
int sd_journal_print(int priority, const char *format, ...) {
int r;
va_list ap;
va_start(ap, format);
r = sd_journal_printv(priority, format, ap);
va_end(ap);
return r;
}
int sd_journal_printv(int priority, const char *format, va_list ap) {
char buffer[8 + LINE_MAX], p[11];
struct iovec iov[2];
if (priority < 0 || priority > 7)
return -EINVAL;
if (!format)
return -EINVAL;
snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
char_array_0(p);
memcpy(buffer, "MESSAGE=", 8);
vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
char_array_0(buffer);
zero(iov);
IOVEC_SET_STRING(iov[0], buffer);
IOVEC_SET_STRING(iov[1], p);
return sd_journal_sendv(iov, 2);
}
int sd_journal_send(const char *format, ...) {
int r, n = 0, i = 0, j;
va_list ap;
struct iovec *iov = NULL;
va_start(ap, format);
while (format) {
struct iovec *c;
char *buffer;
if (i >= n) {
n = MAX(i*2, 4);
c = realloc(iov, n * sizeof(struct iovec));
if (!c) {
r = -ENOMEM;
goto fail;
}
iov = c;
}
if (vasprintf(&buffer, format, ap) < 0) {
r = -ENOMEM;
goto fail;
}
IOVEC_SET_STRING(iov[i++], buffer);
format = va_arg(ap, char *);
}
va_end(ap);
r = sd_journal_sendv(iov, i);
fail:
for (j = 0; j < i; j++)
free(iov[j].iov_base);
free(iov);
return r;
}
int sd_journal_sendv(const struct iovec *iov, int n) {
int fd;
struct iovec *w;
uint64_t *l;
int i, j = 0;
struct msghdr mh;
struct sockaddr_un sa;
if (!iov || n <= 0)
return -EINVAL;
w = alloca(sizeof(struct iovec) * n * 5);
l = alloca(sizeof(uint64_t) * n);
for (i = 0; i < n; i++) {
char *c, *nl;
c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
if (!c)
return -EINVAL;
nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
if (nl) {
if (nl < c)
return -EINVAL;
/* Already includes a newline? Bummer, then
* let's write the variable name, then a
* newline, then the size (64bit LE), followed
* by the data and a final newline */
w[j].iov_base = iov[i].iov_base;
w[j].iov_len = c - (char*) iov[i].iov_base;
j++;
IOVEC_SET_STRING(w[j++], "\n");
l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
w[j].iov_base = &l[i];
w[j].iov_len = sizeof(uint64_t);
j++;
w[j].iov_base = c + 1;
w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
j++;
} else
/* Nothing special? Then just add the line and
* append a newline */
w[j++] = iov[i];
IOVEC_SET_STRING(w[j++], "\n");
}
fd = journal_fd();
if (fd < 0)
return fd;
zero(sa);
sa.sun_family = AF_UNIX;
strncpy(sa.sun_path,"/run/systemd/journal", sizeof(sa.sun_path));
zero(mh);
mh.msg_name = &sa;
mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
mh.msg_iov = w;
mh.msg_iovlen = j;
if (sendmsg(fd, &mh, MSG_NOSIGNAL) < 0)
return -errno;
return 0;
}
int sd_journal_stream_fd(const char *tag, int priority, int priority_prefix) {
union sockaddr_union sa;
int fd;
char *header;
size_t l;
ssize_t r;
if (priority < 0 || priority > 7)
return -EINVAL;
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
if (fd < 0)
return -errno;
zero(sa);
sa.un.sun_family = AF_UNIX;
strncpy(sa.un.sun_path, "/run/systemd/stdout", sizeof(sa.un.sun_path));
r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
if (r < 0) {
close_nointr_nofail(fd);
return -errno;
}
if (!tag)
tag = "";
l = strlen(tag);
header = alloca(l + 1 + 2 + 2 + 2);
memcpy(header, tag, l);
header[l++] = '\n';
header[l++] = '0' + priority;
header[l++] = '\n';
header[l++] = '0' + !!priority_prefix;
header[l++] = '\n';
header[l++] = '0';
header[l++] = '\n';
r = loop_write(fd, header, l, false);
if (r < 0) {
close_nointr_nofail(fd);
return (int) r;
}
if ((size_t) r != l) {
close_nointr_nofail(fd);
return -errno;
}
return fd;
}

544
src/journal/journalctl.c Normal file
View file

@ -0,0 +1,544 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <fcntl.h>
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <time.h>
#include <getopt.h>
#include "sd-journal.h"
#include "log.h"
#include "util.h"
#include "build.h"
#include "pager.h"
#define PRINT_THRESHOLD 128
static enum {
OUTPUT_SHORT,
OUTPUT_VERBOSE,
OUTPUT_EXPORT,
OUTPUT_JSON,
_OUTPUT_MAX
} arg_output = OUTPUT_SHORT;
static bool arg_follow = false;
static bool arg_show_all = false;
static bool arg_no_pager = false;
static bool contains_unprintable(const void *p, size_t l) {
const char *j;
for (j = p; j < (const char *) p + l; j++)
if (*j < ' ' || *j >= 127)
return true;
return false;
}
static int output_short(sd_journal *j, unsigned line) {
int r;
uint64_t realtime;
time_t t;
struct tm tm;
char buf[64];
const void *data;
size_t length;
size_t n = 0;
assert(j);
r = sd_journal_get_realtime_usec(j, &realtime);
if (r < 0) {
log_error("Failed to get realtime: %s", strerror(-r));
return r;
}
t = (time_t) (realtime / USEC_PER_SEC);
if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
log_error("Failed to format time.");
return -EINVAL;
}
fputs(buf, stdout);
n += strlen(buf);
if (sd_journal_get_data(j, "_HOSTNAME", &data, &length) >= 0 &&
(arg_show_all || (!contains_unprintable(data, length) &&
length < PRINT_THRESHOLD))) {
printf(" %.*s", (int) length - 10, ((const char*) data) + 10);
n += length - 10 + 1;
}
if (sd_journal_get_data(j, "MESSAGE", &data, &length) >= 0) {
if (arg_show_all)
printf(" %.*s", (int) length - 8, ((const char*) data) + 8);
else if (contains_unprintable(data, length))
fputs(" [blob data]", stdout);
else if (length - 8 + n < columns())
printf(" %.*s", (int) length - 8, ((const char*) data) + 8);
else if (n < columns()) {
char *e;
e = ellipsize_mem((const char *) data + 8, length - 8, columns() - n - 2, 90);
if (!e)
printf(" %.*s", (int) length - 8, ((const char*) data) + 8);
else
printf(" %s", e);
free(e);
}
}
fputc('\n', stdout);
return 0;
}
static int output_verbose(sd_journal *j, unsigned line) {
const void *data;
size_t length;
char *cursor;
uint64_t realtime;
char ts[FORMAT_TIMESTAMP_MAX];
int r;
assert(j);
r = sd_journal_get_realtime_usec(j, &realtime);
if (r < 0) {
log_error("Failed to get realtime timestamp: %s", strerror(-r));
return r;
}
r = sd_journal_get_cursor(j, &cursor);
if (r < 0) {
log_error("Failed to get cursor: %s", strerror(-r));
return r;
}
printf("%s [%s]\n",
format_timestamp(ts, sizeof(ts), realtime),
cursor);
free(cursor);
SD_JOURNAL_FOREACH_DATA(j, data, length) {
if (!arg_show_all && (length > PRINT_THRESHOLD ||
contains_unprintable(data, length))) {
const char *c;
c = memchr(data, '=', length);
if (!c) {
log_error("Invalid field.");
return -EINVAL;
}
printf("\t%.*s=[blob data]\n",
(int) (c - (const char*) data),
(const char*) data);
} else
printf("\t%.*s\n", (int) length, (const char*) data);
}
return 0;
}
static int output_export(sd_journal *j, unsigned line) {
sd_id128_t boot_id;
char sid[33];
int r;
usec_t realtime, monotonic;
char *cursor;
const void *data;
size_t length;
assert(j);
r = sd_journal_get_realtime_usec(j, &realtime);
if (r < 0) {
log_error("Failed to get realtime timestamp: %s", strerror(-r));
return r;
}
r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
if (r < 0) {
log_error("Failed to get monotonic timestamp: %s", strerror(-r));
return r;
}
r = sd_journal_get_cursor(j, &cursor);
if (r < 0) {
log_error("Failed to get cursor: %s", strerror(-r));
return r;
}
printf(".cursor=%s\n"
".realtime=%llu\n"
".monotonic=%llu\n"
".boot_id=%s\n",
cursor,
(unsigned long long) realtime,
(unsigned long long) monotonic,
sd_id128_to_string(boot_id, sid));
free(cursor);
SD_JOURNAL_FOREACH_DATA(j, data, length) {
if (contains_unprintable(data, length)) {
const char *c;
uint64_t le64;
c = memchr(data, '=', length);
if (!c) {
log_error("Invalid field.");
return -EINVAL;
}
fwrite(data, c - (const char*) data, 1, stdout);
fputc('\n', stdout);
le64 = htole64(length - (c - (const char*) data) - 1);
fwrite(&le64, sizeof(le64), 1, stdout);
fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout);
} else
fwrite(data, length, 1, stdout);
fputc('\n', stdout);
}
fputc('\n', stdout);
return 0;
}
static void json_escape(const char* p, size_t l) {
if (contains_unprintable(p, l)) {
bool not_first = false;
fputs("[ ", stdout);
while (l > 0) {
if (not_first)
printf(", %u", (uint8_t) *p);
else {
not_first = true;
printf("%u", (uint8_t) *p);
}
p++;
l--;
}
fputs(" ]", stdout);
} else {
fputc('\"', stdout);
while (l > 0) {
if (*p == '"' || *p == '\\') {
fputc('\\', stdout);
fputc(*p, stdout);
} else
fputc(*p, stdout);
p++;
l--;
}
fputc('\"', stdout);
}
}
static int output_json(sd_journal *j, unsigned line) {
uint64_t realtime, monotonic;
char *cursor;
const void *data;
size_t length;
sd_id128_t boot_id;
char sid[33];
int r;
assert(j);
r = sd_journal_get_realtime_usec(j, &realtime);
if (r < 0) {
log_error("Failed to get realtime timestamp: %s", strerror(-r));
return r;
}
r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
if (r < 0) {
log_error("Failed to get monotonic timestamp: %s", strerror(-r));
return r;
}
r = sd_journal_get_cursor(j, &cursor);
if (r < 0) {
log_error("Failed to get cursor: %s", strerror(-r));
return r;
}
if (line == 1)
fputc('\n', stdout);
else
fputs(",\n", stdout);
printf("{\n"
"\t\".cursor\" : \"%s\",\n"
"\t\".realtime\" : %llu,\n"
"\t\".monotonic\" : %llu,\n"
"\t\".boot_id\" : \"%s\"",
cursor,
(unsigned long long) realtime,
(unsigned long long) monotonic,
sd_id128_to_string(boot_id, sid));
free(cursor);
SD_JOURNAL_FOREACH_DATA(j, data, length) {
const char *c;
c = memchr(data, '=', length);
if (!c) {
log_error("Invalid field.");
return -EINVAL;
}
fputs(",\n\t", stdout);
json_escape(data, c - (const char*) data);
fputs(" : ", stdout);
json_escape(c + 1, length - (c - (const char*) data) - 1);
}
fputs("\n}", stdout);
fflush(stdout);
return 0;
}
static int (*output_funcs[_OUTPUT_MAX])(sd_journal*j, unsigned line) = {
[OUTPUT_SHORT] = output_short,
[OUTPUT_VERBOSE] = output_verbose,
[OUTPUT_EXPORT] = output_export,
[OUTPUT_JSON] = output_json
};
static int help(void) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the login manager.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" -a --all Show all properties, including long and unprintable\n"
" -f --follow Follow journal\n"
" -o --output=STRING Change output mode (short, verbose, export, json)\n",
program_invocation_short_name);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_NO_PAGER
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version" , no_argument, NULL, ARG_VERSION },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "follow", no_argument, NULL, 'f' },
{ "output", required_argument, NULL, 'o' },
{ "all", no_argument, NULL, 'a' },
{ NULL, 0, NULL, 0 }
};
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hfo:a", options, NULL)) >= 0) {
switch (c) {
case 'h':
help();
return 0;
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(DISTRIBUTION);
puts(SYSTEMD_FEATURES);
return 0;
case ARG_NO_PAGER:
arg_no_pager = true;
break;
case 'f':
arg_follow = true;
break;
case 'o':
if (streq(optarg, "short"))
arg_output = OUTPUT_SHORT;
else if (streq(optarg, "verbose"))
arg_output = OUTPUT_VERBOSE;
else if (streq(optarg, "export"))
arg_output = OUTPUT_EXPORT;
else if (streq(optarg, "json"))
arg_output = OUTPUT_JSON;
else {
log_error("Unknown output '%s'.", optarg);
return -EINVAL;
}
break;
case 'a':
arg_show_all = true;
break;
case '?':
return -EINVAL;
default:
log_error("Unknown option code %c", c);
return -EINVAL;
}
}
return 1;
}
int main(int argc, char *argv[]) {
int r, i, fd;
sd_journal *j = NULL;
unsigned line = 0;
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = sd_journal_open(&j, 0);
if (r < 0) {
log_error("Failed to open journal: %s", strerror(-r));
goto finish;
}
for (i = optind; i < argc; i++) {
r = sd_journal_add_match(j, argv[i], strlen(argv[i]));
if (r < 0) {
log_error("Failed to add match: %s", strerror(-r));
goto finish;
}
}
fd = sd_journal_get_fd(j);
if (fd < 0) {
log_error("Failed to get wakeup fd: %s", strerror(-fd));
goto finish;
}
r = sd_journal_seek_head(j);
if (r < 0) {
log_error("Failed to seek to head: %s", strerror(-r));
goto finish;
}
if (!arg_no_pager && !arg_follow) {
columns();
pager_open();
}
if (arg_output == OUTPUT_JSON) {
fputc('[', stdout);
fflush(stdout);
}
for (;;) {
struct pollfd pollfd;
for (;;) {
r = sd_journal_next(j);
if (r < 0) {
log_error("Failed to iterate through journal: %s", strerror(-r));
goto finish;
}
if (r == 0)
break;
line ++;
r = output_funcs[arg_output](j, line);
if (r < 0)
goto finish;
}
if (!arg_follow)
break;
zero(pollfd);
pollfd.fd = fd;
pollfd.events = POLLIN;
if (poll(&pollfd, 1, -1) < 0) {
if (errno == EINTR)
break;
log_error("poll(): %m");
r = -errno;
goto finish;
}
r = sd_journal_process(j);
if (r < 0) {
log_error("Failed to process: %s", strerror(-r));
goto finish;
}
}
if (arg_output == OUTPUT_JSON)
fputs("\n]\n", stdout);
finish:
if (j)
sd_journal_close(j);
pager_close();
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

1909
src/journal/journald.c Normal file

File diff suppressed because it is too large Load diff

1003
src/journal/lookup3.c Normal file

File diff suppressed because it is too large Load diff

25
src/journal/lookup3.h Normal file
View file

@ -0,0 +1,25 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foolookup3hfoo
#define foolookup3hfoo
#include <inttypes.h>
#include <sys/types.h>
uint32_t jenkins_hashword(const uint32_t *k, size_t length, uint32_t initval);
void jenkins_hashword2(const uint32_t *k, size_t length, uint32_t *pc, uint32_t *pb);
uint32_t jenkins_hashlittle(const void *key, size_t length, uint32_t initval);
void jenkins_hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb);
uint32_t jenkins_hashbig(const void *key, size_t length, uint32_t initval);
static inline uint64_t hash64(const void *data, size_t length) {
uint32_t a = 0, b = 0;
jenkins_hashlittle2(data, length, &a, &b);
return ((uint64_t) a << 32ULL) | (uint64_t) b;
}
#endif

1573
src/journal/sd-journal.c Normal file

File diff suppressed because it is too large Load diff

125
src/journal/sd-journal.h Normal file
View file

@ -0,0 +1,125 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foojournalhfoo
#define foojournalhfoo
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <inttypes.h>
#include <sys/types.h>
#include <stdarg.h>
#include <sys/uio.h>
#include "sd-id128.h"
/* TODO:
*
* - OR of matches is borked...
* - extend hash tables table as we go
* - accelerate looking for "all hostnames" and suchlike.
* - hookup with systemctl
* - handle incomplete header
* - write unit files
*
* - local deserializer
* - http server
* - message catalog
*
* - check LE/BE conversion for 8bit, 16bit, 32bit values
* - cryptographic hash
* - think about manipulations of header
* - implement audit gateway
*/
/* Write to daemon */
int sd_journal_print(int piority, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
int sd_journal_printv(int priority, const char *format, va_list ap);
int sd_journal_send(const char *format, ...) __attribute__((sentinel));
int sd_journal_sendv(const struct iovec *iov, int n);
int sd_journal_stream_fd(const char *tag, int priority, int priority_prefix);
/* Browse journal stream */
typedef struct sd_journal sd_journal;
enum {
SD_JOURNAL_LOCAL_ONLY = 1,
SD_JOURNAL_RUNTIME_ONLY = 2,
SD_JOURNAL_SYSTEM_ONLY = 4
};
int sd_journal_open(sd_journal **ret, int flags);
void sd_journal_close(sd_journal *j);
int sd_journal_previous(sd_journal *j);
int sd_journal_next(sd_journal *j);
int sd_journal_previous_skip(sd_journal *j, uint64_t skip);
int sd_journal_next_skip(sd_journal *j, uint64_t skip);
int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret);
int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id);
int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l);
int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l);
void sd_journal_restart_data(sd_journal *j);
int sd_journal_add_match(sd_journal *j, const void *data, size_t size);
void sd_journal_flush_matches(sd_journal *j);
int sd_journal_seek_head(sd_journal *j);
int sd_journal_seek_tail(sd_journal *j);
int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec);
int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec);
int sd_journal_seek_cursor(sd_journal *j, const char *cursor);
int sd_journal_get_cursor(sd_journal *j, char **cursor);
int sd_journal_query_unique(sd_journal *j, const char *field); /* missing */
int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /* missing */
void sd_journal_restart_unique(sd_journal *j); /* missing */
enum {
SD_JOURNAL_NOP,
SD_JOURNAL_APPEND,
SD_JOURNAL_INVALIDATE_ADD,
SD_JOURNAL_INVALIDATE_REMOVE
};
int sd_journal_get_fd(sd_journal *j);
int sd_journal_process(sd_journal *j);
#define SD_JOURNAL_FOREACH(j) \
if (sd_journal_seek_head(j) >= 0) \
while (sd_journal_next(j) > 0)
#define SD_JOURNAL_FOREACH_BACKWARDS(j) \
if (sd_journal_seek_tail(j) >= 0) \
while (sd_journal_previous(j) > 0)
#define SD_JOURNAL_FOREACH_DATA(j, data, l) \
for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \
for (sd_journal_restart_unique(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
#endif

119
src/journal/test-journal.c Normal file
View file

@ -0,0 +1,119 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <fcntl.h>
#include <unistd.h>
#include "sd-journal.h"
#include "journal-file.h"
#include "log.h"
int main(int argc, char *argv[]) {
dual_timestamp ts;
JournalFile *f;
struct iovec iovec;
static const char test[] = "test", test2[] = "test2";
Object *o;
uint64_t p;
log_set_max_level(LOG_DEBUG);
unlink("test.journal");
assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, NULL, &f) == 0);
dual_timestamp_get(&ts);
iovec.iov_base = (void*) test;
iovec.iov_len = strlen(test);
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
iovec.iov_base = (void*) test2;
iovec.iov_len = strlen(test2);
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
iovec.iov_base = (void*) test;
iovec.iov_len = strlen(test);
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
journal_file_dump(f);
assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1);
assert(le64toh(o->entry.seqnum) == 1);
assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 1);
assert(le64toh(o->entry.seqnum) == 2);
assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 1);
assert(le64toh(o->entry.seqnum) == 3);
assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 0);
assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1);
assert(le64toh(o->entry.seqnum) == 1);
assert(journal_file_skip_entry(f, o, p, 2, &o, &p) == 1);
assert(le64toh(o->entry.seqnum) == 3);
assert(journal_file_skip_entry(f, o, p, -2, &o, &p) == 1);
assert(le64toh(o->entry.seqnum) == 1);
assert(journal_file_skip_entry(f, o, p, -2, &o, &p) == 1);
assert(le64toh(o->entry.seqnum) == 1);
assert(journal_file_find_data_object(f, test, strlen(test), NULL, &p) == 1);
assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1);
assert(le64toh(o->entry.seqnum) == 1);
assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1);
assert(le64toh(o->entry.seqnum) == 3);
assert(journal_file_find_data_object(f, test2, strlen(test2), NULL, &p) == 1);
assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1);
assert(le64toh(o->entry.seqnum) == 2);
assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1);
assert(le64toh(o->entry.seqnum) == 2);
assert(journal_file_find_data_object(f, "quux", 4, NULL, &p) == 0);
assert(journal_file_move_to_entry_by_seqnum(f, 1, DIRECTION_DOWN, &o, NULL) == 1);
assert(le64toh(o->entry.seqnum) == 1);
assert(journal_file_move_to_entry_by_seqnum(f, 3, DIRECTION_DOWN, &o, NULL) == 1);
assert(le64toh(o->entry.seqnum) == 3);
assert(journal_file_move_to_entry_by_seqnum(f, 2, DIRECTION_DOWN, &o, NULL) == 1);
assert(le64toh(o->entry.seqnum) == 2);
assert(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0);
journal_file_rotate(&f);
journal_file_rotate(&f);
journal_file_close(f);
journal_directory_vacuum(".", 3000000, 0);
log_error("Exiting...");
return 0;
}

View file

@ -65,63 +65,72 @@ static void server_done(Server *s) {
fdset_free(s->syslog_fds);
}
static int server_init(Server *s, unsigned n_sockets) {
int r;
unsigned i;
static int server_init(Server *s) {
int i, r, n;
struct epoll_event ev;
sigset_t mask;
assert(s);
assert(n_sockets > 0);
zero(*s);
s->kmsg_fd = s->signal_fd = -1;
if ((s->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0) {
r = -errno;
log_error("Failed to create epoll object: %s", strerror(errno));
goto fail;
s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (s->epoll_fd < 0) {
log_error("Failed to create epoll object: %m");
return -errno;
}
if (!(s->syslog_fds = fdset_new())) {
r = -ENOMEM;
log_error("Failed to allocate file descriptor set: %s", strerror(errno));
goto fail;
s->syslog_fds = fdset_new();
if (!s->syslog_fds) {
log_error("Failed to allocate file descriptor set: %s", strerror(ENOMEM));
return -ENOMEM;
}
for (i = 0; i < n_sockets; i++) {
int fd;
n = sd_listen_fds(true);
if (n < 0) {
log_error("Failed to read listening file descriptors from environment: %s", strerror(-n));
return n;
}
if (n <= 0 || n > SERVER_FD_MAX) {
log_error("No or too many file descriptors passed.");
return -EINVAL;
}
for (i = 0; i < n; i++) {
int fd, one = 1;
fd = SD_LISTEN_FDS_START+i;
if ((r = sd_is_socket(fd, AF_UNSPEC, SOCK_DGRAM, -1)) < 0) {
r = sd_is_socket(fd, AF_UNSPEC, SOCK_DGRAM, -1);
if (r < 0) {
log_error("Failed to determine file descriptor type: %s", strerror(-r));
goto fail;
return r;
}
if (!r) {
log_error("Wrong file descriptor type.");
r = -EINVAL;
goto fail;
return -EINVAL;
}
zero(ev);
ev.events = EPOLLIN;
ev.data.fd = fd;
if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
r = -errno;
log_error("Failed to add server fd to epoll object: %s", strerror(errno));
goto fail;
log_error("Failed to add server fd to epoll object: %m");
return -errno;
}
if ((r = fdset_put(s->syslog_fds, fd)) < 0) {
r = fdset_put(s->syslog_fds, fd);
if (r < 0) {
log_error("Failed to store file descriptor in set: %s", strerror(-r));
goto fail;
return r;
}
}
if ((s->kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) {
s->kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
if (s->kmsg_fd < 0) {
log_error("Failed to open /dev/kmsg for logging: %m");
return -errno;
}
@ -130,7 +139,8 @@ static int server_init(Server *s, unsigned n_sockets) {
sigset_add_many(&mask, SIGINT, SIGTERM, -1);
assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
if ((s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
if (s->signal_fd < 0) {
log_error("signalfd(): %m");
return -errno;
}
@ -145,80 +155,6 @@ static int server_init(Server *s, unsigned n_sockets) {
}
return 0;
fail:
server_done(s);
return r;
}
static void skip_date(const char **buf) {
enum {
LETTER,
SPACE,
NUMBER,
SPACE_OR_NUMBER,
COLON
} sequence[] = {
LETTER, LETTER, LETTER,
SPACE,
SPACE_OR_NUMBER, NUMBER,
SPACE,
SPACE_OR_NUMBER, NUMBER,
COLON,
SPACE_OR_NUMBER, NUMBER,
COLON,
SPACE_OR_NUMBER, NUMBER,
SPACE
};
const char *p;
unsigned i;
assert(buf);
assert(*buf);
p = *buf;
for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
if (!*p)
return;
switch (sequence[i]) {
case SPACE:
if (*p != ' ')
return;
break;
case SPACE_OR_NUMBER:
if (*p == ' ')
break;
/* fall through */
case NUMBER:
if (*p < '0' || *p > '9')
return;
break;
case LETTER:
if (!(*p >= 'A' && *p <= 'Z') &&
!(*p >= 'a' && *p <= 'z'))
return;
break;
case COLON:
if (*p != ':')
return;
break;
}
}
*buf = p;
}
static int read_process(const char **buf, struct iovec *iovec) {
@ -263,28 +199,6 @@ static int read_process(const char **buf, struct iovec *iovec) {
return 1;
}
static void skip_pid(const char **buf) {
const char *p;
assert(buf);
assert(*buf);
p = *buf;
if (*p != '[')
return;
p++;
p += strspn(p, "0123456789");
if (*p != ']')
return;
p++;
*buf = p;
}
static int write_message(Server *s, const char *buf, struct ucred *ucred) {
ssize_t k;
char priority[6], pid[16];
@ -311,14 +225,14 @@ static int write_message(Server *s, const char *buf, struct ucred *ucred) {
IOVEC_SET_STRING(iovec[i++], priority);
/* Second, skip date */
skip_date(&buf);
skip_syslog_date((char**) &buf);
/* Then, add process if set */
if (read_process(&buf, &iovec[i]) > 0)
i++;
else if (ucred &&
ucred->pid > 0 &&
get_process_name(ucred->pid, &process) >= 0)
get_process_comm(ucred->pid, &process) >= 0)
IOVEC_SET_STRING(iovec[i++], process);
/* Skip the stored PID if we have a better one */
@ -327,7 +241,7 @@ static int write_message(Server *s, const char *buf, struct ucred *ucred) {
char_array_0(pid);
IOVEC_SET_STRING(iovec[i++], pid);
skip_pid(&buf);
skip_syslog_pid((char**) &buf);
if (*buf == ':')
buf++;
@ -365,7 +279,8 @@ static int process_event(Server *s, struct epoll_event *ev) {
struct signalfd_siginfo sfsi;
ssize_t n;
if ((n = read(s->signal_fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
n = read(s->signal_fd, &sfsi, sizeof(sfsi));
if (n != sizeof(sfsi)) {
if (n >= 0)
return -EIO;
@ -404,7 +319,8 @@ static int process_event(Server *s, struct epoll_event *ev) {
msghdr.msg_control = &control;
msghdr.msg_controllen = sizeof(control);
if ((n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT)) < 0) {
n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT);
if (n < 0) {
if (errno == EINTR || errno == EAGAIN)
return 1;
@ -421,12 +337,14 @@ static int process_event(Server *s, struct epoll_event *ev) {
else
ucred = NULL;
if ((e = memchr(buf, '\n', n)))
e = memchr(buf, '\n', n);
if (e)
*e = 0;
else
buf[n] = 0;
if ((k = write_message(s, strstrip(buf), ucred)) < 0)
k = write_message(s, strstrip(buf), ucred);
if (k < 0)
return k;
}
}
@ -436,7 +354,7 @@ static int process_event(Server *s, struct epoll_event *ev) {
int main(int argc, char *argv[]) {
Server server;
int r = EXIT_FAILURE, n;
int r;
if (getppid() != 1) {
log_error("This program should be invoked by init only.");
@ -454,18 +372,9 @@ int main(int argc, char *argv[]) {
umask(0022);
if ((n = sd_listen_fds(true)) < 0) {
log_error("Failed to read listening file descriptors from environment: %s", strerror(-r));
return EXIT_FAILURE;
}
if (n <= 0 || n > SERVER_FD_MAX) {
log_error("No or too many file descriptors passed.");
return EXIT_FAILURE;
}
if (server_init(&server, (unsigned) n) < 0)
return EXIT_FAILURE;
r = server_init(&server);
if (r < 0)
goto finish;
log_debug("systemd-kmsg-syslogd running as pid %lu", (unsigned long) getpid());
@ -475,36 +384,33 @@ int main(int argc, char *argv[]) {
for (;;) {
struct epoll_event event;
int k;
if ((k = epoll_wait(server.epoll_fd, &event, 1, -1)) < 0) {
r = epoll_wait(server.epoll_fd, &event, 1, -1);
if (r < 0) {
if (errno == EINTR)
continue;
log_error("epoll_wait() failed: %m");
goto fail;
}
if (k <= 0)
r = -errno;
goto finish;
} else if (r == 0)
break;
if ((k = process_event(&server, &event)) < 0)
goto fail;
if (k == 0)
r = process_event(&server, &event);
if (r < 0)
goto finish;
else if (r == 0)
break;
}
r = EXIT_SUCCESS;
log_debug("systemd-kmsg-syslogd stopped as pid %lu", (unsigned long) getpid());
fail:
finish:
sd_notify(false,
"STATUS=Shutting down...");
server_done(&server);
return r;
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

22
src/libsystemd-id128.sym Normal file
View file

@ -0,0 +1,22 @@
/***
This file is part of systemd.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***/
/* Original symbols from systemd v38 */
LIBSYSTEMD_ID128_38 {
global:
sd_id128_to_string;
sd_id128_from_string;
sd_id128_randomize;
sd_id128_make_v4_uuid;
sd_id128_get_machine;
sd_id128_get_boot;
local:
*;
};

View file

@ -0,0 +1,45 @@
/***
This file is part of systemd.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***/
/* Original symbols from systemd v38 */
LIBSYSTEMD_JOURNAL_38 {
global:
sd_journal_print;
sd_journal_printv;
sd_journal_send;
sd_journal_sendv;
sd_journal_stream_fd;
sd_journal_open;
sd_journal_close;
sd_journal_previous;
sd_journal_next;
sd_journal_previous_skip;
sd_journal_next_skip;
sd_journal_get_realtime_usec;
sd_journal_get_monotonic_usec;
sd_journal_get_data;
sd_journal_enumerate_data;
sd_journal_restart_data;
sd_journal_add_match;
sd_journal_flush_matches;
sd_journal_seek_head;
sd_journal_seek_tail;
sd_journal_seek_monotonic_usec;
sd_journal_seek_realtime_usec;
sd_journal_seek_cursor;
sd_journal_get_cursor;
sd_journal_query_unique;
sd_journal_enumerate_unique;
sd_journal_restart_unique;
sd_journal_get_fd;
sd_journal_process;
local:
*;
};

View file

@ -393,7 +393,7 @@ static void print_session_status_info(SessionStatusInfo *i) {
printf("\t Leader: %u", (unsigned) i->leader);
get_process_name(i->leader, &t);
get_process_comm(i->leader, &t);
if (t) {
printf(" (%s)", t);
free(t);

View file

@ -27,46 +27,7 @@
#include "logind-acl.h"
#include "util.h"
static int find_acl(acl_t acl, uid_t uid, acl_entry_t *entry) {
acl_entry_t i;
int found;
assert(acl);
assert(entry);
for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
found > 0;
found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
acl_tag_t tag;
uid_t *u;
bool b;
if (acl_get_tag_type(i, &tag) < 0)
return -errno;
if (tag != ACL_USER)
continue;
u = acl_get_qualifier(i);
if (!u)
return -errno;
b = *u == uid;
acl_free(u);
if (b) {
*entry = i;
return 1;
}
}
if (found < 0)
return -errno;
return 0;
}
#include "acl-util.h"
static int flush_acl(acl_t acl) {
acl_entry_t i;
@ -125,7 +86,7 @@ int devnode_acl(const char *path,
} else if (del && old_uid > 0) {
acl_entry_t entry;
r = find_acl(acl, old_uid, &entry);
r = acl_find_uid(acl, old_uid, &entry);
if (r < 0)
goto finish;
@ -144,7 +105,7 @@ int devnode_acl(const char *path,
acl_permset_t permset;
int rd, wt;
r = find_acl(acl, new_uid, &entry);
r = acl_find_uid(acl, new_uid, &entry);
if (r < 0)
goto finish;

View file

@ -31,21 +31,12 @@
#include "macro.h"
#include "util.h"
#include "log.h"
static void make_v4_uuid(unsigned char *id) {
/* Stolen from generate_random_uuid() of drivers/char/random.c
* in the kernel sources */
/* Set UUID version to 4 --- truly random generation */
id[6] = (id[6] & 0x0F) | 0x40;
/* Set the UUID variant to DCE */
id[8] = (id[8] & 0x3F) | 0x80;
}
#include "sd-id128.h"
static int generate(char id[34]) {
int fd;
unsigned char buf[16], *p;
int fd, r;
unsigned char *p;
sd_id128_t buf;
char *q;
ssize_t k;
@ -68,26 +59,13 @@ static int generate(char id[34]) {
}
/* If that didn't work, generate a random machine id */
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0) {
log_error("Failed to open /dev/urandom: %m");
return -errno;
r = sd_id128_randomize(&buf);
if (r < 0) {
log_error("Failed to open /dev/urandom: %s", strerror(-r));
return r;
}
k = loop_read(fd, buf, sizeof(buf), false);
close_nointr_nofail(fd);
if (k != sizeof(buf)) {
log_error("Failed to read /dev/urandom: %s", strerror(k < 0 ? -k : EIO));
return k < 0 ? (int) k : -EIO;
}
/* Turn this into a valid v4 UUID, to be nice. Note that we
* only guarantee this for newly generated UUIDs, not for
* pre-existing ones.*/
make_v4_uuid(buf);
for (p = buf, q = id; p < buf + sizeof(buf); p++, q += 2) {
for (p = buf.bytes, q = id; p < buf.bytes + sizeof(buf); p++, q += 2) {
q[0] = hexchar(*p >> 4);
q[1] = hexchar(*p & 15);
}

View file

@ -149,7 +149,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
char *_s = (char *)(s); \
_i->iov_base = _s; \
_i->iov_len = strlen(_s); \
} while(false);
} while(false)
static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
unsigned j;

View file

@ -2032,7 +2032,7 @@ static int manager_dispatch_sigchld(Manager *m) {
if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) {
char *name = NULL;
get_process_name(si.si_pid, &name);
get_process_comm(si.si_pid, &name);
log_debug("Got SIGCHLD for process %lu (%s)", (unsigned long) si.si_pid, strna(name));
free(name);
}
@ -2117,7 +2117,7 @@ static int manager_process_signal_fd(Manager *m) {
if (sfsi.ssi_pid > 0) {
char *p = NULL;
get_process_name(sfsi.ssi_pid, &p);
get_process_comm(sfsi.ssi_pid, &p);
log_debug("Received SIG%s from PID %lu (%s).",
signal_to_string(sfsi.ssi_signo),

View file

@ -163,42 +163,24 @@ static int get_user_data(
const char *username = NULL;
struct passwd *pw = NULL;
uid_t uid;
int r;
bool have_loginuid = false;
char *s;
assert(handle);
assert(ret_username);
assert(ret_pw);
if (have_effective_cap(CAP_AUDIT_CONTROL) > 0) {
/* Only use audit login uid if we are executed with
* sufficient capabilities so that pam_loginuid could
* do its job. If we are lacking the CAP_AUDIT_CONTROL
* capabality we most likely are being run in a
* container and /proc/self/loginuid is useless since
* it probably contains a uid of the host system. */
if (read_one_line_file("/proc/self/loginuid", &s) >= 0) {
uid_t uid;
r = parse_uid(s, &uid);
free(s);
if (r >= 0 && uid != (uint32_t) -1) {
have_loginuid = true;
pw = pam_modutil_getpwuid(handle, uid);
}
}
}
if (!have_loginuid) {
if ((r = pam_get_user(handle, &username, NULL)) != PAM_SUCCESS) {
r = audit_loginuid_from_pid(0, &uid);
if (r >= 0)
pw = pam_modutil_getpwuid(handle, uid);
else {
r = pam_get_user(handle, &username, NULL);
if (r != PAM_SUCCESS) {
pam_syslog(handle, LOG_ERR, "Failed to get user name.");
return r;
}
if (!username || !*username) {
if (isempty(username)) {
pam_syslog(handle, LOG_ERR, "User name not valid.");
return PAM_AUTH_ERR;
}

View file

@ -54,12 +54,14 @@ int main(int argc, char *argv[]) {
umask(0022);
if (!(f = setmntent("/etc/fstab", "r"))) {
f = setmntent("/etc/fstab", "r");
if (!f) {
log_error("Failed to open /etc/fstab: %m");
goto finish;
}
if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
pids = hashmap_new(trivial_hash_func, trivial_compare_func);
if (!pids) {
log_error("Failed to allocate set");
goto finish;
}
@ -76,9 +78,10 @@ int main(int argc, char *argv[]) {
log_debug("Remounting %s", me->mnt_dir);
if ((pid = fork()) < 0) {
pid = fork();
if (pid < 0) {
log_error("Failed to fork: %m");
ret = 1;
ret = EXIT_FAILURE;
continue;
}
@ -101,8 +104,15 @@ int main(int argc, char *argv[]) {
/* Parent */
s = strdup(me->mnt_dir);
if (!s) {
log_error("Out of memory.");
ret = EXIT_FAILURE;
continue;
}
if ((k = hashmap_put(pids, UINT_TO_PTR(pid), s)) < 0) {
k = hashmap_put(pids, UINT_TO_PTR(pid), s);
if (k < 0) {
log_error("Failed to add PID to set: %s", strerror(-k));
ret = EXIT_FAILURE;
continue;
@ -124,7 +134,8 @@ int main(int argc, char *argv[]) {
break;
}
if ((s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid));
if (s) {
if (!is_clean_exit(si.si_code, si.si_status)) {
if (si.si_code == CLD_EXITED)
log_error("/bin/mount for %s exited with exit status %i.", s, si.si_status);

210
src/sd-id128.c Normal file
View file

@ -0,0 +1,210 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include "sd-id128.h"
#include "util.h"
#include "macro.h"
char *sd_id128_to_string(sd_id128_t id, char s[33]) {
unsigned n;
assert(s);
for (n = 0; n < 16; n++) {
s[n*2] = hexchar(id.bytes[n] >> 4);
s[n*2+1] = hexchar(id.bytes[n] & 0xF);
}
s[32] = 0;
return s;
}
int sd_id128_from_string(const char s[33], sd_id128_t *ret) {
unsigned n;
sd_id128_t t;
assert(s);
assert(ret);
for (n = 0; n < 16; n++) {
int a, b;
a = unhexchar(s[n*2]);
if (a < 0)
return -EINVAL;
b = unhexchar(s[n*2+1]);
if (b < 0)
return -EINVAL;
t.bytes[n] = (a << 4) | b;
}
if (s[32] != 0)
return -EINVAL;
*ret = t;
return 0;
}
sd_id128_t sd_id128_make_v4_uuid(sd_id128_t id) {
/* Stolen from generate_random_uuid() of drivers/char/random.c
* in the kernel sources */
/* Set UUID version to 4 --- truly random generation */
id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
/* Set the UUID variant to DCE */
id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
return id;
}
int sd_id128_get_machine(sd_id128_t *ret) {
static __thread sd_id128_t saved_machine_id;
static __thread bool saved_machine_id_valid = false;
int fd;
char buf[32];
ssize_t k;
unsigned j;
sd_id128_t t;
if (saved_machine_id_valid) {
*ret = saved_machine_id;
return 0;
}
fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return -errno;
k = loop_read(fd, buf, 32, false);
close_nointr_nofail(fd);
if (k < 0)
return (int) k;
if (k < 32)
return -EIO;
for (j = 0; j < 16; j++) {
int a, b;
a = unhexchar(buf[j*2]);
b = unhexchar(buf[j*2+1]);
if (a < 0 || b < 0)
return -EIO;
t.bytes[j] = a << 4 | b;
}
saved_machine_id = t;
saved_machine_id_valid = true;
*ret = t;
return 0;
}
int sd_id128_get_boot(sd_id128_t *ret) {
static __thread sd_id128_t saved_boot_id;
static __thread bool saved_boot_id_valid = false;
int fd;
char buf[36];
ssize_t k;
unsigned j;
sd_id128_t t;
char *p;
if (saved_boot_id_valid) {
*ret = saved_boot_id;
return 0;
}
fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return -errno;
k = loop_read(fd, buf, 36, false);
close_nointr_nofail(fd);
if (k < 0)
return (int) k;
if (k < 36)
return -EIO;
for (j = 0, p = buf; j < 16; j++) {
int a, b;
if (*p == '-')
p++;
a = unhexchar(p[0]);
b = unhexchar(p[1]);
if (a < 0 || b < 0)
return -EIO;
t.bytes[j] = a << 4 | b;
p += 2;
}
saved_boot_id = t;
saved_boot_id_valid = true;
*ret = t;
return 0;
}
int sd_id128_randomize(sd_id128_t *ret) {
int fd;
ssize_t k;
sd_id128_t t;
assert(ret);
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return -errno;
k = loop_read(fd, &t, 16, false);
close_nointr_nofail(fd);
if (k < 0)
return (int) k;
if (k < 16)
return -EIO;
/* Turn this into a valid v4 UUID, to be nice. Note that we
* only guarantee this for newly generated UUIDs, not for
* pre-existing ones.*/
*ret = sd_id128_make_v4_uuid(t);
return 0;
}

56
src/sd-id128.h Normal file
View file

@ -0,0 +1,56 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef fooid128hfoo
#define fooid128hfoo
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
typedef union sd_id128 sd_id128_t;
union sd_id128 {
uint8_t bytes[16];
uint64_t qwords[2];
};
char *sd_id128_to_string(sd_id128_t id, char s[33]);
int sd_id128_from_string(const char s[33], sd_id128_t *ret);
int sd_id128_randomize(sd_id128_t *ret);
sd_id128_t sd_id128_make_v4_uuid(sd_id128_t id);
int sd_id128_get_machine(sd_id128_t *ret);
int sd_id128_get_boot(sd_id128_t *ret);
#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
((sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \
0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }})
static inline bool sd_id128_equal(sd_id128_t a, sd_id128_t b) {
return memcmp(&a, &b, 16) == 0;
}
#endif

View file

@ -236,7 +236,6 @@ static int stream_log(Stream *s, char *p, usec_t ts) {
writev(console, iovec, 4);
}
}
return 0;
@ -366,7 +365,6 @@ static int stream_process(Stream *s, usec_t ts) {
return -errno;
}
if (l == 0)
return 0;
@ -409,8 +407,10 @@ static int stream_new(Server *s, int server_fd) {
int r;
assert(s);
assert(server_fd >= 0);
if ((fd = accept4(server_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC)) < 0)
fd = accept4(server_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (fd < 0)
return -errno;
if (s->n_streams >= STREAMS_MAX) {
@ -649,7 +649,8 @@ int main(int argc, char *argv[]) {
umask(0022);
if ((n = sd_listen_fds(true)) < 0) {
n = sd_listen_fds(true);
if (n < 0) {
log_error("Failed to read listening file descriptors from environment: %s", strerror(-r));
return EXIT_FAILURE;
}

View file

@ -2199,7 +2199,7 @@ static void print_status_info(UnitStatusInfo *i) {
if (i->running) {
char *t = NULL;
get_process_name(i->main_pid, &t);
get_process_comm(i->main_pid, &t);
if (t) {
printf(" (%s)", t);
free(t);
@ -2233,7 +2233,7 @@ static void print_status_info(UnitStatusInfo *i) {
printf(" Control: %u", (unsigned) i->control_pid);
get_process_name(i->control_pid, &t);
get_process_comm(i->control_pid, &t);
if (t) {
printf(" (%s)", t);
free(t);

49
src/test-id128.c Normal file
View file

@ -0,0 +1,49 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <string.h>
#include "sd-id128.h"
#include "util.h"
#include "macro.h"
#define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10)
int main(int argc, char *argv[]) {
sd_id128_t id, id2;
char t[33];
assert_se(sd_id128_randomize(&id) == 0);
printf("random: %s\n", sd_id128_to_string(id, t));
assert_se(sd_id128_from_string(t, &id2) == 0);
assert_se(sd_id128_equal(id, id2));
assert_se(sd_id128_get_machine(&id) == 0);
printf("machine: %s\n", sd_id128_to_string(id, t));
assert_se(sd_id128_get_boot(&id) == 0);
printf("boot: %s\n", sd_id128_to_string(id, t));
printf("waldi: %s\n", sd_id128_to_string(ID128_WALDI, t));
return 0;
}

View file

@ -55,6 +55,7 @@
#include <linux/rtc.h>
#include <glob.h>
#include <grp.h>
#include <sys/mman.h>
#include "macro.h"
#include "util.h"
@ -73,7 +74,7 @@ size_t page_size(void) {
static __thread size_t pgsz = 0;
long r;
if (_likely_(pgsz))
if (_likely_(pgsz > 0))
return pgsz;
assert_se((r = sysconf(_SC_PAGESIZE)) > 0);
@ -993,46 +994,51 @@ char *truncate_nl(char *s) {
return s;
}
int get_process_name(pid_t pid, char **name) {
char *p;
int get_process_comm(pid_t pid, char **name) {
int r;
assert(pid >= 1);
assert(name);
if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
return -ENOMEM;
if (pid == 0)
r = read_one_line_file("/proc/self/comm", name);
else {
char *p;
if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
return -ENOMEM;
r = read_one_line_file(p, name);
free(p);
r = read_one_line_file(p, name);
free(p);
}
if (r < 0)
return r;
return 0;
return r;
}
int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
char *p, *r, *k;
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
char *r, *k;
int c;
bool space = false;
size_t left;
FILE *f;
assert(pid >= 1);
assert(max_length > 0);
assert(line);
if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
return -ENOMEM;
if (pid == 0)
f = fopen("/proc/self/cmdline", "re");
else {
char *p;
if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
return -ENOMEM;
f = fopen(p, "re");
free(p);
f = fopen(p, "re");
free(p);
}
if (!f)
return -errno;
if (!(r = new(char, max_length))) {
r = new(char, max_length);
if (!r) {
fclose(f);
return -ENOMEM;
}
@ -1076,13 +1082,17 @@ int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
free(r);
if ((h = get_process_name(pid, &t)) < 0)
if (!comm_fallback)
return -ENOENT;
h = get_process_comm(pid, &t);
if (h < 0)
return h;
h = asprintf(&r, "[%s]", t);
r = join("[", t, "]", NULL);
free(t);
if (h < 0)
if (!r)
return -ENOMEM;
}
@ -1090,6 +1100,25 @@ int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
return 0;
}
int get_process_exe(pid_t pid, char **name) {
int r;
assert(name);
if (pid == 0)
r = readlink_malloc("/proc/self/exe", name);
else {
char *p;
if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
return -ENOMEM;
r = readlink_malloc(p, name);
free(p);
}
return r;
}
char *strnappend(const char *s, const char *suffix, size_t b) {
size_t a;
char *r;
@ -2645,7 +2674,7 @@ int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocst
ssize_t l;
struct inotify_event *e;
if ((l = read(notify, &inotify_buffer, sizeof(inotify_buffer))) < 0) {
if ((l = read(notify, inotify_buffer, sizeof(inotify_buffer))) < 0) {
if (errno == EINTR)
continue;
@ -2856,7 +2885,8 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
while (nbytes > 0) {
ssize_t k;
if ((k = write(fd, p, nbytes)) <= 0) {
k = write(fd, p, nbytes);
if (k <= 0) {
if (k < 0 && errno == EINTR)
continue;
@ -3503,6 +3533,22 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
return 0;
}
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
assert(fd >= 0);
/* Under the assumption that we are running privileged we
* first change the access mode and only then hand out
* ownership to avoid a window where access is too open. */
if (fchmod(fd, mode) < 0)
return -errno;
if (fchown(fd, uid, gid) < 0)
return -errno;
return 0;
}
cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
cpu_set_t *r;
unsigned n = 1024;
@ -3860,7 +3906,7 @@ char **replace_env_argv(char **argv, char **env) {
return r;
}
int columns(void) {
unsigned columns(void) {
static __thread int parsed_columns = 0;
const char *e;
@ -3903,38 +3949,41 @@ int running_in_chroot(void) {
a.st_ino != b.st_ino;
}
char *ellipsize(const char *s, unsigned length, unsigned percent) {
size_t l, x;
char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
size_t x;
char *r;
assert(s);
assert(percent <= 100);
assert(length >= 3);
assert(new_length >= 3);
l = strlen(s);
if (old_length <= 3 || old_length <= new_length)
return strndup(s, old_length);
if (l <= 3 || l <= length)
return strdup(s);
if (!(r = new0(char, length+1)))
r = new0(char, new_length+1);
if (!r)
return r;
x = (length * percent) / 100;
x = (new_length * percent) / 100;
if (x > length - 3)
x = length - 3;
if (x > new_length - 3)
x = new_length - 3;
memcpy(r, s, x);
r[x] = '.';
r[x+1] = '.';
r[x+2] = '.';
memcpy(r + x + 3,
s + l - (length - x - 3),
length - x - 3);
s + old_length - (new_length - x - 3),
new_length - x - 3);
return r;
}
char *ellipsize(const char *s, size_t length, unsigned percent) {
return ellipsize_mem(s, strlen(s), length, percent);
}
int touch(const char *path) {
int fd;
@ -4270,7 +4319,7 @@ const char *default_term_for_tty(const char *tty) {
return term;
}
bool dirent_is_file(struct dirent *de) {
bool dirent_is_file(const struct dirent *de) {
assert(de);
if (ignore_file(de->d_name))
@ -4284,6 +4333,15 @@ bool dirent_is_file(struct dirent *de) {
return true;
}
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
assert(de);
if (!dirent_is_file(de))
return false;
return endswith(de->d_name, suffix);
}
void execute_directory(const char *directory, DIR *d, char *argv[]) {
DIR *_d = NULL;
struct dirent *de;
@ -4456,6 +4514,98 @@ void parse_syslog_priority(char **p, int *priority) {
*p += k;
}
void skip_syslog_pid(char **buf) {
char *p;
assert(buf);
assert(*buf);
p = *buf;
if (*p != '[')
return;
p++;
p += strspn(p, "0123456789");
if (*p != ']')
return;
p++;
*buf = p;
}
void skip_syslog_date(char **buf) {
enum {
LETTER,
SPACE,
NUMBER,
SPACE_OR_NUMBER,
COLON
} sequence[] = {
LETTER, LETTER, LETTER,
SPACE,
SPACE_OR_NUMBER, NUMBER,
SPACE,
SPACE_OR_NUMBER, NUMBER,
COLON,
SPACE_OR_NUMBER, NUMBER,
COLON,
SPACE_OR_NUMBER, NUMBER,
SPACE
};
char *p;
unsigned i;
assert(buf);
assert(*buf);
p = *buf;
for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
if (!*p)
return;
switch (sequence[i]) {
case SPACE:
if (*p != ' ')
return;
break;
case SPACE_OR_NUMBER:
if (*p == ' ')
break;
/* fall through */
case NUMBER:
if (*p < '0' || *p > '9')
return;
break;
case LETTER:
if (!(*p >= 'A' && *p <= 'Z') &&
!(*p >= 'a' && *p <= 'z'))
return;
break;
case COLON:
if (*p != ':')
return;
break;
}
}
*buf = p;
}
int have_effective_cap(int value) {
cap_t cap;
cap_flag_value_t fv;
@ -4675,21 +4825,6 @@ int vt_disallocate(const char *name) {
return 0;
}
static int file_is_conf(const struct dirent *d, const char *suffix) {
assert(d);
if (ignore_file(d->d_name))
return 0;
if (d->d_type != DT_REG &&
d->d_type != DT_LNK &&
d->d_type != DT_UNKNOWN)
return 0;
return endswith(d->d_name, suffix);
}
static int files_add(Hashmap *h, const char *path, const char *suffix) {
DIR *dir;
struct dirent buffer, *de;
@ -4715,7 +4850,7 @@ static int files_add(Hashmap *h, const char *path, const char *suffix) {
if (!de)
break;
if (!file_is_conf(de, suffix))
if (!dirent_is_file_with_suffix(de, suffix))
continue;
if (asprintf(&p, "%s/%s", path, de->d_name) < 0) {
@ -5066,21 +5201,27 @@ int symlink_or_copy_atomic(const char *from, const char *to) {
}
int audit_session_from_pid(pid_t pid, uint32_t *id) {
char *p, *s;
char *s;
uint32_t u;
int r;
assert(pid >= 1);
assert(id);
if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
return -ENOENT;
if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
return -ENOMEM;
if (pid == 0)
r = read_one_line_file("/proc/self/sessionid", &s);
else {
char *p;
if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
return -ENOMEM;
r = read_one_line_file(p, &s);
free(p);
}
r = read_one_line_file(p, &s);
free(p);
if (r < 0)
return r;
@ -5097,6 +5238,51 @@ int audit_session_from_pid(pid_t pid, uint32_t *id) {
return 0;
}
int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
char *s;
uid_t u;
int r;
assert(uid);
/* Only use audit login uid if we are executed with sufficient
* capabilities so that pam_loginuid could do its job. If we
* are lacking the CAP_AUDIT_CONTROL capabality we most likely
* are being run in a container and /proc/self/loginuid is
* useless since it probably contains a uid of the host
* system. */
if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
return -ENOENT;
if (pid == 0)
r = read_one_line_file("/proc/self/loginuid", &s);
else {
char *p;
if (asprintf(&p, "/proc/%lu/loginuid", (unsigned long) pid) < 0)
return -ENOMEM;
r = read_one_line_file(p, &s);
free(p);
}
if (r < 0)
return r;
r = parse_uid(s, &u);
free(s);
if (r < 0)
return r;
if (u == (uid_t) -1)
return -ENOENT;
*uid = (uid_t) u;
return 0;
}
bool display_is_local(const char *display) {
assert(display);
@ -5704,6 +5890,24 @@ int strdup_or_null(const char *a, char **b) {
return 0;
}
int prot_from_flags(int flags) {
switch (flags & O_ACCMODE) {
case O_RDONLY:
return PROT_READ;
case O_WRONLY:
return PROT_WRITE;
case O_RDWR:
return PROT_READ|PROT_WRITE;
default:
return -EINVAL;
}
}
unsigned long cap_last_cap(void) {
static __thread unsigned long saved;
static __thread bool valid = false;

View file

@ -248,8 +248,9 @@ int parent_of_path(const char *path, char **parent);
int rmdir_parents(const char *path, const char *stop);
int get_process_name(pid_t pid, char **name);
int get_process_cmdline(pid_t pid, size_t max_length, char **line);
int get_process_comm(pid_t pid, char **name);
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
int get_process_exe(pid_t pid, char **name);
char hexchar(int x);
int unhexchar(char c);
@ -274,7 +275,9 @@ bool path_equal(const char *a, const char *b);
char *ascii_strlower(char *path);
bool dirent_is_file(struct dirent *de);
bool dirent_is_file(const struct dirent *de);
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix);
bool ignore_file(const char *filename);
bool chars_intersect(const char *a, const char *b);
@ -363,6 +366,7 @@ int get_ctty_devnr(pid_t pid, dev_t *d);
int get_ctty(pid_t, dev_t *_devnr, char **r);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
@ -374,11 +378,12 @@ void status_vprintf(const char *format, va_list ap);
void status_printf(const char *format, ...);
void status_welcome(void);
int columns(void);
unsigned columns(void);
int running_in_chroot(void);
char *ellipsize(const char *s, unsigned length, unsigned percent);
char *ellipsize(const char *s, size_t length, unsigned percent);
char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent);
int touch(const char *path);
@ -415,6 +420,8 @@ bool nulstr_contains(const char*nulstr, const char *needle);
bool plymouth_running(void);
void parse_syslog_priority(char **p, int *priority);
void skip_syslog_pid(char **buf);
void skip_syslog_date(char **buf);
int have_effective_cap(int value);
@ -443,6 +450,7 @@ int hwclock_get_time(struct tm *tm);
int hwclock_set_time(const struct tm *tm);
int audit_session_from_pid(pid_t pid, uint32_t *id);
int audit_loginuid_from_pid(pid_t pid, uid_t *uid);
bool display_is_local(const char *display);
int socket_from_display(const char *display, char **path);
@ -506,6 +514,8 @@ extern char **saved_argv;
bool kexec_loaded(void);
int prot_from_flags(int flags);
unsigned long cap_last_cap(void);
#endif

1
tmpfiles.d/Makefile Symbolic link
View file

@ -0,0 +1 @@
../src/Makefile

1
units/.gitignore vendored
View file

@ -1,3 +1,4 @@
/systemd-journald.service
user@.service
systemd-logind.service
systemd-localed.service

View file

@ -16,7 +16,7 @@ Before=sockets.target syslog.target
Wants=syslog.target
[Socket]
ListenDatagram=/dev/log
ListenDatagram=/run/systemd/syslog
SocketMode=0666
PassCred=yes

View file

@ -0,0 +1,24 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# See systemd.special(7) for details
[Unit]
Description=Journal Service
DefaultDependencies=no
Requires=systemd-journald.socket
After=systemd-journald.socket
[Service]
ExecStart=@rootlibexecdir@/systemd-journald
NotifyAccess=all
StandardOutput=null
#CapabilityBoundingSet=CAP_SYS_ADMIN CAP_SETUID CAP_SETGID
# Increase the default a bit in order to allow many simultaneous
# services being run since we keep one fd open per service.
LimitNOFILE=16384

View file

@ -0,0 +1,24 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# See systemd.special(7) for details
[Unit]
Description=Journal Socket
DefaultDependencies=no
Before=sockets.target syslog.target
# Mount and swap units need this. If this socket unit is removed by an
# isolate request the mount and and swap units would be removed too,
# hence let's exclude this from isolate requests.
IgnoreOnIsolate=yes
[Socket]
ListenStream=/run/systemd/stdout
ListenDatagram=/run/systemd/native
ListenDatagram=/dev/log
SocketMode=0666