chiark / gitweb /
Merge pull request #19 from elogind/dev_v231
authorSven Eden <yamakuzure@gmx.net>
Mon, 3 Jul 2017 13:28:24 +0000 (15:28 +0200)
committerGitHub <noreply@github.com>
Mon, 3 Jul 2017 13:28:24 +0000 (15:28 +0200)
Merge dev_v231 into master

233 files changed:
.dir-locals.el
.gitignore
.mailmap
.vimrc
CODING_STYLE
Makefile.am
NEWS
README
TODO
cb/elogind.cbp
coccinelle/xsprintf.cocci [deleted file]
configure.ac
man/custom-html.xsl
man/elogind.xml
man/loginctl.xml
man/logind.conf.xml
man/sd_event_add_io.xml
man/sd_event_now.xml
man/sd_event_source_get_pending.xml
man/sd_event_source_set_priority.xml
man/sd_get_seats.xml
man/sd_id128_to_string.xml
man/sd_machine_get_class.xml
man/sd_notify.xml
man/sd_seat_get_active.xml
man/sd_session_is_active.xml
man/sd_watchdog_enabled.xml
man/standard-conf.xml
po/.gitignore
po/LINGUAS
po/POTFILES.skip
po/be.po
po/be@latin.po
po/bg.po [new file with mode: 0644]
po/da.po [new file with mode: 0644]
po/el.po
po/es.po
po/fr.po
po/hr.po [new file with mode: 0644]
po/hu.po
po/id.po [new file with mode: 0755]
po/it.po
po/pl.po
po/pt_BR.po
po/ru.po
po/sv.po
po/tr.po
po/uk.po
po/zh_CN.po [new file with mode: 0644]
po/zh_TW.po
src/.gitignore
src/basic/alloc-util.c
src/basic/alloc-util.h
src/basic/cgroup-util.c
src/basic/cgroup-util.h
src/basic/copy.c
src/basic/copy.h
src/basic/def.h
src/basic/dirent-util.c
src/basic/dirent-util.h
src/basic/escape.c
src/basic/escape.h
src/basic/extract-word.c
src/basic/fd-util.c
src/basic/fd-util.h
src/basic/fileio-label.h
src/basic/fileio.c
src/basic/fileio.h
src/basic/formats-util.h
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/gunicode.h
src/basic/hash-funcs.c
src/basic/hash-funcs.h
src/basic/hashmap.c
src/basic/hashmap.h
src/basic/hexdecoct.c
src/basic/hostname-util.c
src/basic/hostname-util.h
src/basic/io-util.c
src/basic/io-util.h
src/basic/list.h
src/basic/locale-util.c
src/basic/locale-util.h
src/basic/log.c
src/basic/log.h
src/basic/login-util.h
src/basic/macro.h
src/basic/memfd-util.c
src/basic/memfd-util.h
src/basic/mempool.h
src/basic/missing.h
src/basic/missing_syscall.h [new file with mode: 0644]
src/basic/mkdir.c
src/basic/mount-util.c
src/basic/mount-util.h
src/basic/parse-util.c
src/basic/parse-util.h
src/basic/path-util.c
src/basic/path-util.h
src/basic/proc-cmdline.c
src/basic/process-util.c
src/basic/process-util.h
src/basic/random-util.c
src/basic/rm-rf.c
src/basic/rm-rf.h
src/basic/selinux-util.c
src/basic/selinux-util.h
src/basic/set.h
src/basic/signal-util.c
src/basic/signal-util.h
src/basic/siphash24.c
src/basic/socket-util.c
src/basic/socket-util.h
src/basic/stdio-util.h
src/basic/string-table.h
src/basic/string-util.c
src/basic/string-util.h
src/basic/strv.c
src/basic/strv.h
src/basic/terminal-util.c
src/basic/terminal-util.h
src/basic/time-util.c
src/basic/time-util.h
src/basic/umask-util.h
src/basic/unaligned.h
src/basic/unit-name.c
src/basic/unit-name.h
src/basic/user-util.c
src/basic/user-util.h
src/basic/utf8.c
src/basic/utf8.h
src/basic/util.c
src/basic/util.h
src/basic/virt.c
src/basic/virt.h
src/basic/xattr-util.c
src/cgroups-agent/cgroups-agent.c
src/core/cgroup.c
src/core/cgroup.h
src/core/mount-setup.c
src/libelogind/libelogind.pc.in
src/libelogind/libelogind.sym
src/libelogind/sd-bus/bus-common-errors.c
src/libelogind/sd-bus/bus-common-errors.h
src/libelogind/sd-bus/bus-control.c
src/libelogind/sd-bus/bus-convenience.c
src/libelogind/sd-bus/bus-introspect.c
src/libelogind/sd-bus/bus-kernel.c
src/libelogind/sd-bus/bus-match.c
src/libelogind/sd-bus/bus-message.c
src/libelogind/sd-bus/bus-objects.c
src/libelogind/sd-bus/bus-slot.c
src/libelogind/sd-bus/bus-socket.c
src/libelogind/sd-bus/bus-track.c
src/libelogind/sd-bus/sd-bus.c
src/libelogind/sd-daemon/sd-daemon.c
src/libelogind/sd-event/sd-event.c
src/libelogind/sd-id128/id128-util.c [new file with mode: 0644]
src/libelogind/sd-id128/id128-util.h [new file with mode: 0644]
src/libelogind/sd-id128/sd-id128.c
src/libelogind/sd-login/sd-login.c
src/libelogind/sd-login/test-login.c
src/login/.gitignore
src/login/70-uaccess.rules
src/login/eloginctl.c [new file with mode: 0644]
src/login/eloginctl.h [new file with mode: 0644]
src/login/elogind-action.c [new file with mode: 0644]
src/login/elogind-action.h [new file with mode: 0644]
src/login/elogind-dbus.c [new file with mode: 0644]
src/login/elogind-dbus.h [new file with mode: 0644]
src/login/elogind-user.m4
src/login/elogind.c [new file with mode: 0644]
src/login/elogind.h [new file with mode: 0644]
src/login/loginctl.c
src/login/logind-action.c
src/login/logind-action.h
src/login/logind-core.c
src/login/logind-dbus.c
src/login/logind-gperf.gperf
src/login/logind-inhibit.c
src/login/logind-seat-dbus.c
src/login/logind-seat.c
src/login/logind-session-dbus.c
src/login/logind-session-device.c
src/login/logind-session.c
src/login/logind-session.h
src/login/logind-user-dbus.c
src/login/logind-user.c
src/login/logind-user.h
src/login/logind-utmp.c [new file with mode: 0644]
src/login/logind.c
src/login/logind.conf.in [moved from src/login/logind.conf with 91% similarity]
src/login/logind.h
src/login/org.freedesktop.login1.conf
src/login/org.freedesktop.login1.policy.in
src/login/org.freedesktop.login1.service
src/login/pam_elogind.c
src/login/sysfs-show.c
src/login/test-login-shared.c
src/login/test-login-tables.c
src/shared/acl-util.c
src/shared/bus-util.c
src/shared/bus-util.h
src/shared/clean-ipc.c
src/shared/conf-parser.c
src/shared/conf-parser.h
src/shared/musl_missing.c [moved from src/basic/musl_missing.c with 100% similarity]
src/shared/musl_missing.h [moved from src/basic/musl_missing.h with 90% similarity]
src/shared/pager.c
src/shared/pager.h
src/shared/path-lookup.h [deleted file]
src/shared/sleep-config.c [moved from src/login/logind-sleep.c with 62% similarity]
src/shared/sleep-config.h [moved from src/login/logind-sleep.h with 72% similarity]
src/shared/spawn-polkit-agent.c
src/shared/udev-util.h
src/shared/utmp-wtmp.c [new file with mode: 0644]
src/shared/utmp-wtmp.h [new file with mode: 0644]
src/sleep/Makefile [new symlink]
src/sleep/sleep.c [new file with mode: 0644]
src/sleep/sleep.h [new file with mode: 0644]
src/systemd/_sd-common.h
src/systemd/sd-bus-protocol.h
src/systemd/sd-bus-vtable.h
src/systemd/sd-bus.h
src/systemd/sd-daemon.h
src/systemd/sd-event.h
src/systemd/sd-id128.h
src/systemd/sd-login.h
src/systemd/sd-messages.h
src/update-utmp/Makefile [new symlink]
src/update-utmp/update-utmp.c [new file with mode: 0644]
src/update-utmp/update-utmp.h [new file with mode: 0644]

index 9d9f8cd178c96e16ded975a09045d09e0d5b2f19..3e1b2d76c070c5f36504eae6fd5d37c815ef6cdd 100644 (file)
@@ -2,6 +2,22 @@
 ; A list of (major-mode . ((var1 . value1) (var2 . value2)))
 ; Mode can be nil, which gives default values.
 
+; Note that we set a line width of 119 for .c and XML files, but for everything
+; else (such as journal catalog files, unit files, README files) we stick to a
+; more conservative 79 characters.
+
+; NOTE: If you update this file make sure to update .vimrc and .editorconfig,
+; too.
+
 ((nil . ((indent-tabs-mode . nil)
-         (tab-width . 8)))
-)
+         (tab-width . 8)
+         (fill-column . 79)))
+ (c-mode . ((fill-column . 119)
+            (c-basic-offset . 8)
+            (eval . (c-set-offset 'substatement-open 0))
+            (eval . (c-set-offset 'statement-case-open 0))
+            (eval . (c-set-offset 'case-label 0))
+            (eval . (c-set-offset 'arglist-intro '++))
+            (eval . (c-set-offset 'arglist-close 0))))
+ (nxml-mode . ((nxml-child-indent . 2)
+               (fill-column . 119))))
index 356388b5cc5403de03863357c0c8a93aa055dcfb..00e474d9b250e1de07867f791b18f89f9c5b2501 100644 (file)
@@ -6,7 +6,6 @@
 *.log
 *.o
 *.plist
-*.pyc
 *.stamp
 *.swp
 *.trs
@@ -40,7 +39,6 @@
 /hostnamectl
 /install-tree
 /journalctl
-/libsystemd-*.c
 /libtool
 /linuxx64.efi.stub
 /localectl
 /mtd_probe
 /networkctl
 /scsi_id
-/systemadm
 /systemctl
 /systemd
 /systemd-ac-power
-/systemd-activate
 /systemd-analyze
 /systemd-ask-password
 /systemd-backlight
 /systemd-binfmt
-/systemd-bootchart
 /systemd-bootx64.efi
-/systemd-bus-proxyd
 /systemd-cat
 /systemd-cgls
 /systemd-cgroups-agent
@@ -78,7 +72,6 @@
 /systemd-fsck
 /systemd-fstab-generator
 /systemd-getty-generator
-/systemd-gnome-ask-password-agent
 /systemd-gpt-auto-generator
 /systemd-hibernate-resume
 /systemd-hibernate-resume-generator
@@ -92,7 +85,6 @@
 /systemd-journal-remote
 /systemd-journal-upload
 /systemd-journald
-/systemd-kmsg-syslogd
 /systemd-localed
 /systemd-logind
 /systemd-machine-id-setup
 /systemd-quotacheck
 /systemd-random-seed
 /systemd-rc-local-generator
-/systemd-remount-api-vfs
 /systemd-remount-fs
 /systemd-reply-password
 /systemd-resolve-host
 /systemd-run
 /systemd-shutdown
 /systemd-sleep
+/systemd-socket-activate
 /systemd-socket-proxyd
 /systemd-stdio-bridge
 /systemd-sysctl
 /systemd-timesyncd
 /systemd-tmpfiles
 /systemd-tty-ask-password-agent
-/systemd-uaccess
 /systemd-udevd
 /systemd-update-done
 /systemd-update-utmp
 /tags
 /test-acd
 /test-af-list
+/test-alloc-util
 /test-architecture
 /test-arphrd-list
 /test-async
 /test-audit-type
 /test-barrier
 /test-bitmap
-/test-boot-timestamp
+/test-boot-timestamps
 /test-btrfs
 /test-bus-benchmark
 /test-bus-chat
 /test-bus-match
 /test-bus-objects
 /test-bus-policy
-/test-bus-proxy
 /test-bus-server
 /test-bus-signature
 /test-bus-zero-copy
 /test-cgroup
 /test-cgroup-mask
 /test-cgroup-util
+/test-clock
 /test-compress
 /test-compress-benchmark
 /test-condition
 /test-conf-parser
 /test-copy
 /test-coredump-vacuum
+/test-cpu-set-util
 /test-daemon
 /test-date
 /test-device-nodes
 /test-journal-stream
 /test-journal-syslog
 /test-journal-verify
-/test-json
+/test-keymap-util
 /test-libsystemd-sym*
 /test-libudev
 /test-libudev-sym*
 /test-util
 /test-verbs
 /test-watchdog
+/test-web-util
+/test-xattr-util
 /test-xml
 /timedatectl
 /udevadm
 /v4l_id
 Makefile.in
 __pycache__/
+*.py[co]
 aclocal.m4
 config.h
 config.h.in
@@ -295,7 +291,6 @@ stamp-*
 /elogind-inhibit
 /test-libelogind*
 
-
 # Local Helper Scripts and Tools - Not for distribution
 patches/
 /check_*.*
@@ -309,3 +304,18 @@ patches/
 *.remote
 *.bak
 *.layout
+
+# directories not needed by elogind
+/sysusers.d
+/hwdb
+/catalog
+/xorg
+/network
+/system-preset
+/tmpfiles.d
+/units
+/rules
+/test
+/.github
+/sysctl.d
+/coccinelle
index 69060957dad2f4f527cbfd38407d6d47d54ac633..d56fb6784526798a9d141919ac25aa2c981a8b60 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -64,3 +64,13 @@ Tom Rini <trini@kernel.crashing.org>
 Paul Mundt <lethal@linux-sh.org>
 Atul Sabharwal <atul.sabharwal@intel.com>
 Daniel Machon <Danielmachon@live.dk>
+Thomas Blume <Thomas.Blume@suse.com>
+Pablo Lezaeta Reyes <prflr88@gmail.com>
+Otto Wallenius <otto_026@hotmail.com>
+Tom Yan <tom.ty89@gmail.com>
+Marty Plummer <ntzrmtthihu777@gmail.com>
+Brian Boylston <brian.boylston@hpe.com>
+Thomas H. P. Andersen <phomes@gmail.com>
+Michael Olbrich <m.olbrich@pengutronix.de>
+Douglas Christman <DouglasChristman@gmail.com>
+Alexander Kuleshov <kuleshovmail@gmail.com> <0xAX@users.noreply.github.com>
diff --git a/.vimrc b/.vimrc
index b802c908f268d686c31b7fc6f5e7d0375b27abfe..284bf88494c574f0aefb4f76650b5a1320af4489 100644 (file)
--- a/.vimrc
+++ b/.vimrc
@@ -1,5 +1,20 @@
 " 'set exrc' in ~/.vimrc will read .vimrc from the current directory
+" Warning: Enabling exrc is dangerous! You can do nearly everything from a
+" vimrc configuration file, including write operations and shell execution.
+" You should consider setting 'set secure' as well, which is highly
+" recommended!
+
+" Note that we set a line width of 119 for .c and XML files, but for everything
+" else (such as journal catalog files, unit files, README files) we stick to a
+" more conservative 79 characters.
+
+" NOTE: If you update this file make sure to update .dir-locals.el and
+" .editorconfig, too.
+
 set tabstop=8
 set shiftwidth=8
 set expandtab
 set makeprg=GCC_COLORS=\ make
+set tw=79
+au BufRead,BufNewFile *.xml set tw=119 shiftwidth=2 smarttab
+au FileType c set tw=119
index 46e366898e7ee5ddeac6882ef9fa51c081de7cd0..e89b3c67e5166e9ce62904baee55b08a10eb289b 100644 (file)
   programming error with assert_return() and return a sensible return
   code. In all other calls, it is recommended to check for programming
   errors with a more brutal assert(). We are more forgiving to public
-  users then for ourselves! Note that assert() and assert_return()
+  users than for ourselves! Note that assert() and assert_return()
   really only should be used for detecting programming errors, not for
   runtime errors. assert() and assert_return() by usage of _likely_()
   inform the compiler that he should not expect these checks to fail,
   b) socket() and socketpair() must get SOCK_CLOEXEC passed
   c) recvmsg() must get MSG_CMSG_CLOEXEC set
   d) F_DUPFD_CLOEXEC should be used instead of F_DUPFD, and so on
+  f) invocations of fopen() should take "e"
 
 - We never use the POSIX version of basename() (which glibc defines it in
   libgen.h), only the GNU version (which glibc defines in string.h).
 
       unlink("/foo/bar/baz");
 
+  Don't cast function calls to (void) that return no error
+  conditions. Specifically, the various xyz_unref() calls that return a NULL
+  object shouldn't be cast to (void), since not using the return value does not
+  hide any errors.
+
 - Don't invoke exit(), ever. It is not replacement for proper error
   handling. Please escalate errors up your call chain, and use normal
   "return" to exit from the main function of a process. If you
   tools, and we should continue to do so, as it makes it easy to
   identify command line parameter variables, and makes it clear why it
   is OK that they are global variables.
+
+- When exposing public C APIs, be careful what function parameters you make
+  "const". For example, a parameter taking a context object should probably not
+  be "const", even if you are writing an other-wise read-only accessor function
+  for it. The reason is that making it "const" fixates the contract that your
+  call won't alter the object ever, as part of the API. However, that's often
+  quite a promise, given that this even prohibits object-internal caching or
+  lazy initialization of object variables. Moreover it's usually not too useful
+  for client applications. Hence: please be careful and avoid "const" on object
+  parameters, unless you are very sure "const" is appropriate.
+
+- Make sure to enforce limits on every user controllable resource. If the user
+  can allocate resources in your code, your code must enforce some form of
+  limits after which it will refuse operation. It's fine if it is hardcoded (at
+  least initially), but it needs to be there. This is particularly important
+  for objects that unprivileged users may allocate, but also matters for
+  everything else any user may allocated.
+
+- htonl()/ntohl() and htons()/ntohs() are weird. Please use htobe32() and
+  htobe16() instead, it's much more descriptive, and actually says what really
+  is happening, after all htonl() and htons() don't operation on longs and
+  shorts as their name would suggest, but on uint32_t and uint16_t. Also,
+  "network byte order" is just a weird name for "big endian", hence we might
+  want to call it "big endian" right-away.
+
+- You might wonder what kind of common code belongs in src/shared/ and what
+  belongs in src/basic/. The split is like this: anything that uses public APIs
+  we expose (i.e. any of the sd-bus, sd-login, sd-id128, ... APIs) must be
+  located in src/shared/. All stuff that only uses external libraries from
+  other projects (such as glibc's APIs), or APIs from src/basic/ itself should
+  be placed in src/basic/. Conversely, src/libsystemd/ may only use symbols
+  from src/basic, but not from src/shared/. To summarize:
+
+  src/basic/      → may be used by all code in the tree
+                  → may not use any code outside of src/basic/
+
+  src/libsystemd/ → may be used by all code in the tree, except for code in src/basic/
+                  → may not use any code outside of src/basic/, src/libsystemd/
+
+  src/shared/     → may be used by all code in the tree, except for code in src/basic/, src/libsystemd/
+                  → may not use any code outside of src/basic/, src/libsystemd/, src/shared/
+
+- Our focus is on the GNU libc (glibc), not any other libcs. If other libcs are
+  incompatible with glibc it's on them. However, if there are equivalent POSIX
+  and Linux/GNU-specific APIs, we generally prefer the POSIX APIs. If there
+  aren't, we are happy to use GNU or Linux APIs, and expect non-GNU
+  implementations of libc to catch up with glibc.
index 7facc7610600c1c5d8ad875a88b5947ab74fcbb8..1e1870c8106e90d299a240d23311861b00e0fd06 100644 (file)
@@ -38,9 +38,9 @@ SUBDIRS = . po
 # Keep the test-suite.log
 .PRECIOUS: $(TEST_SUITE_LOG) Makefile
 
-LIBELOGIND_CURRENT=14
-LIBELOGIND_REVISION=0
-LIBELOGIND_AGE=14
+LIBELOGIND_CURRENT=16
+LIBELOGIND_REVISION=3
+LIBELOGIND_AGE=16
 
 # Dirs of external packages
 dbuspolicydir=@dbuspolicydir@
@@ -58,7 +58,7 @@ PKTTYAGENT=$(bindir)/pkttyagent
 
 # Our own, non-special dirs
 pkgsysconfdir=$(sysconfdir)/elogind
-pkgincludedir=$(includedir)/elogind
+pkgincludedir=$(includedir)/elogind/systemd
 udevrulesdir=@udevrulesdir@
 udevbindir=@udevbindir@
 udevlibexecdir=$(udevbindir)
@@ -90,10 +90,12 @@ polkitpolicy_files =
 dist_udevrules_DATA =
 nodist_udevrules_DATA =
 dist_pkgsysconf_DATA =
+nodist_pkgsysconf_DATA =
 dist_dbuspolicy_DATA =
 dist_dbussystemservice_DATA =
 check_PROGRAMS =
 check_DATA =
+dist_rootlibexec_DATA =
 tests=
 manual_tests =
 if ENABLE_TESTS
@@ -128,7 +130,7 @@ AM_CPPFLAGS = \
        -include $(top_builddir)/config.h \
        -DPKGSYSCONFDIR=\"$(pkgsysconfdir)\" \
        -DSYSTEMD_CGROUP_CONTROLLER=\"$(CGROUP_CONTROLLER)\" \
-       -DELOGIND_CGROUP_AGENT_PATH=\"$(rootlibexecdir)/elogind-cgroups-agent\" \
+       -DSYSTEMD_CGROUP_AGENT_PATH=\"$(rootlibexecdir)/elogind-cgroups-agent\" \
        -DUDEVLIBEXECDIR=\"$(udevlibexecdir)\" \
        -DPOLKIT_AGENT_BINARY_PATH=\"$(PKTTYAGENT)\" \
        -DSYSTEM_SLEEP_PATH=\"$(systemsleepdir)\" \
@@ -151,6 +153,9 @@ AM_CPPFLAGS = \
        -I $(top_srcdir)/src/libelogind/sd-bus \
        -I $(top_srcdir)/src/libelogind/sd-event \
        -I $(top_srcdir)/src/libelogind/sd-login \
+       -I $(top_srcdir)/src/libelogind/sd-id128 \
+       -I $(top_srcdir)/src/update-utmp \
+       -I $(top_srcdir)/src/sleep \
        $(OUR_CPPFLAGS)
 
 AM_CFLAGS = $(OUR_CFLAGS)
@@ -297,8 +302,6 @@ noinst_LTLIBRARIES += \
 
 libbasic_la_SOURCES = \
        src/basic/missing.h \
-       src/basic/musl_missing.h \
-       src/basic/musl_missing.c \
        src/basic/capability-util.c \
        src/basic/capability-util.h \
        src/basic/conf-files.c \
@@ -343,6 +346,8 @@ libbasic_la_SOURCES = \
        src/basic/escape.h \
        src/basic/path-util.c \
        src/basic/path-util.h \
+       src/basic/parse-printf-format.c \
+       src/basic/parse-printf-format.h \
        src/basic/time-util.c \
        src/basic/time-util.h \
        src/basic/locale-util.c \
@@ -412,9 +417,7 @@ libbasic_la_SOURCES = \
        src/basic/copy.c \
        src/basic/copy.h \
        src/basic/alloc-util.h \
-       src/basic/alloc-util.c \
-       src/basic/parse-printf-format.c \
-       src/basic/parse-printf-format.h
+       src/basic/alloc-util.c
 
 nodist_libbasic_la_SOURCES = \
        src/basic/errno-from-name.h \
@@ -440,16 +443,20 @@ noinst_LTLIBRARIES += \
        libshared.la
 
 libshared_la_SOURCES = \
+       src/shared/bus-util.c \
+       src/shared/bus-util.h \
+       src/shared/clean-ipc.c \
+       src/shared/clean-ipc.h \
        src/shared/conf-parser.c \
        src/shared/conf-parser.h \
+       src/shared/musl_missing.h \
+       src/shared/musl_missing.c \
        src/shared/pager.c \
        src/shared/pager.h \
+       src/shared/sleep-config.c \
+       src/shared/sleep-config.h \
        src/shared/spawn-polkit-agent.c \
-       src/shared/spawn-polkit-agent.h \
-       src/shared/clean-ipc.c \
-       src/shared/clean-ipc.h \
-       src/shared/bus-util.c \
-       src/shared/bus-util.h
+       src/shared/spawn-polkit-agent.h
 
 if HAVE_ACL
 libshared_la_SOURCES += \
@@ -463,9 +470,45 @@ libshared_la_CFLAGS = \
 
 libshared_la_LIBADD = \
        libelogind-internal.la \
+       libbasic.la \
        $(UDEV_LIBS) \
        $(ACL_LIBS)
 
+noinst_LTLIBRARIES += \
+       libelogind-shared.la
+
+libelogind_shared_la_SOURCES = \
+       $(libbasic_la_SOURCES) \
+       $(libshared_la_SOURCES) \
+       $(libelogind_internal_la_SOURCES)
+
+libelogind_shared_la_CFLAGS = \
+       $(AM_CFLAGS) \
+       $(libbasic_la_CFLAGS) \
+       $(libshared_la_CFLAGS) \
+       $(libelogind_internal_la_CFLAGS) \
+       $(libelogind_journal_internal_la_CFLAGS) \
+       $(libudev_internal_la_CFLAGS) \
+       $(ACL_CFLAGS) \
+       $(LIBIDN_CFLAGS) \
+       $(SECCOMP_CFLAGS) \
+       -fvisibility=default
+
+# We can't use libshared_la_LIBADD here because it would
+# pull in libelogind*-internal.la
+libelogind_shared_la_LIBADD = \
+       $(libbasic_la_LIBADD) \
+       $(libelogind_internal_la_LIBADD) \
+       $(UDEV_LIBS) \
+       $(ACL_LIBS) \
+       $(LIBIDN_LIBS) \
+       $(SECCOMP_LIBS)
+
+libelogind_shared_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       -release $(PACKAGE_VERSION)
+
+ # -----------------------------------------------------------------------------
 gperf_txt_sources = \
        src/basic/errno-list.txt
 
@@ -521,7 +564,7 @@ elogind_cgroups_agent_SOURCES = \
        src/cgroups-agent/cgroups-agent.c
 
 elogind_cgroups_agent_LDADD = \
-       libshared.la
+       libelogind-shared.la
 
 # ------------------------------------------------------------------------------
 libelogind_internal_la_SOURCES = \
@@ -574,13 +617,11 @@ libelogind_internal_la_SOURCES = \
        src/libelogind/sd-bus/bus-protocol.h \
        src/libelogind/sd-event/sd-event.c \
        src/libelogind/sd-id128/sd-id128.c \
+       src/libelogind/sd-id128/id128-util.h \
+       src/libelogind/sd-id128/id128-util.c \
        src/libelogind/sd-daemon/sd-daemon.c \
        src/libelogind/sd-login/sd-login.c
 
-libelogind_internal_la_LIBADD = \
-       libbasic.la \
-       -lresolv
-
 noinst_LTLIBRARIES += \
        libelogind-internal.la
 
@@ -589,14 +630,7 @@ EXTRA_DIST += \
        src/libelogind/sd-bus/DIFFERENCES \
        src/libelogind/sd-bus/GVARIANT-SERIALIZATION
 
-libelogind_la_SOURCES = \
-       $(libelogind_internal_la_SOURCES)
-
-nodist_libelogind_la_SOURCES = \
-       $(nodist_libelogind_internal_la_SOURCES)
-
-libelogind_la_CFLAGS = \
-       $(libelogind_internal_la_CFLAGS)
+libelogind_la_SOURCES =
 
 libelogind_la_LDFLAGS = \
        $(AM_LDFLAGS) \
@@ -604,7 +638,8 @@ libelogind_la_LDFLAGS = \
        -Wl,--version-script=$(top_srcdir)/src/libelogind/libelogind.sym
 
 libelogind_la_LIBADD = \
-       $(libelogind_internal_la_LIBADD)
+       libelogind-internal.la \
+       libbasic.la
 
 libelogind-install-hook:
        libname=libelogind.so && $(move-to-rootlibdir)
@@ -624,6 +659,19 @@ pkginclude_HEADERS += \
        src/systemd/sd-id128.h \
        src/systemd/_sd-common.h
 
+header-install-hook:
+       $(MKDIR_P) $(DESTDIR)/$(pkgincludedir)
+       cd $(DESTDIR)/$(includedir)/elogind && \
+               for hdr in $(notdir $(pkginclude_HEADERS)) ; do \
+                       rm -f $$hdr ; \
+                       $(LN_S) systemd/$$hdr $$hdr ; \
+               done
+
+header-uninstall-hook:
+       m -f $(DESTDIR)/$(includedir)/elogind/*.h
+
+INSTALL_EXEC_HOOKS += header-install-hook
+UNINSTALL_EXEC_HOOKS += header-uninstall-hook
 
 lib_LTLIBRARIES += \
        libelogind.la
@@ -640,6 +688,16 @@ elogind_LDADD = \
        libelogind-core.la
 
 libelogind_core_la_SOURCES = \
+       src/core/cgroup.h \
+       src/core/cgroup.c \
+       src/core/mount-setup.h \
+       src/core/mount-setup.c \
+        src/login/elogind.c \
+        src/login/elogind.h \
+        src/login/elogind-action.c \
+        src/login/elogind-action.h \
+       src/login/elogind-dbus.c \
+       src/login/elogind-dbus.h \
        src/login/logind-core.c \
        src/login/logind-device.c \
        src/login/logind-device.h \
@@ -653,8 +711,6 @@ libelogind_core_la_SOURCES = \
        src/login/logind-session.h \
        src/login/logind-session-device.c \
        src/login/logind-session-device.h \
-       src/login/logind-sleep.c \
-       src/login/logind-sleep.h \
        src/login/logind-user.c \
        src/login/logind-user.h \
        src/login/logind-inhibit.c \
@@ -663,14 +719,19 @@ libelogind_core_la_SOURCES = \
        src/login/logind-session-dbus.c \
        src/login/logind-seat-dbus.c \
        src/login/logind-user-dbus.c \
+       src/login/logind-utmp.c \
        src/login/logind-acl.h \
-       src/core/cgroup.h \
-       src/core/cgroup.c \
-       src/core/mount-setup.h \
-       src/core/mount-setup.c
+       src/sleep/sleep.c \
+       src/sleep/sleep.h
+
+if HAVE_UTMP
+libelogind_core_la_SOURCES += \
+       src/shared/utmp-wtmp.c \
+       src/update-utmp/update-utmp.c
+endif
 
 libelogind_core_la_LIBADD = \
-       libshared.la
+       libelogind-shared.la
 
 if HAVE_ACL
 libelogind_core_la_SOURCES += \
@@ -684,12 +745,14 @@ pkglibexec_PROGRAMS += \
        elogind
 
 loginctl_SOURCES = \
+       src/login/eloginctl.c \
+       src/login/eloginctl.h \
        src/login/loginctl.c \
        src/login/sysfs-show.h \
        src/login/sysfs-show.c
 
 loginctl_LDADD = \
-       libshared.la
+       libelogind-shared.la
 
 rootbin_PROGRAMS += \
        loginctl
@@ -705,7 +768,7 @@ elogind_inhibit_SOURCES = \
        src/login/inhibit.c
 
 elogind_inhibit_LDADD = \
-       libshared.la
+       libelogind-shared.la
 
 rootbin_PROGRAMS += \
        elogind-inhibit
@@ -714,19 +777,19 @@ test_login_SOURCES = \
        src/libelogind/sd-login/test-login.c
 
 test_login_LDADD = \
-       libshared.la
+       libelogind-shared.la
 
 test_login_shared_SOURCES = \
        src/login/test-login-shared.c
 
 test_login_shared_LDADD = \
-       libshared.la
+       libelogind-shared.la
 
 test_inhibit_SOURCES = \
        src/login/test-inhibit.c
 
 test_inhibit_LDADD = \
-       libshared.la
+       libelogind-shared.la
 
 test_login_tables_SOURCES = \
        src/login/test-login-tables.c
@@ -779,7 +842,7 @@ dist_dbussystemservice_DATA += \
 dist_dbuspolicy_DATA += \
        src/login/org.freedesktop.login1.conf
 
-dist_pkgsysconf_DATA += \
+nodist_pkgsysconf_DATA += \
        src/login/logind.conf
 
 polkitpolicy_files += \
@@ -801,7 +864,8 @@ gperf_gperf_sources = \
 
 EXTRA_DIST += \
        src/login/71-seat.rules.in \
-       src/login/73-seat-late.rules.in
+       src/login/73-seat-late.rules.in \
+       src/login/logind.conf.in
 
 # ------------------------------------------------------------------------------
 substitutions = \
@@ -823,6 +887,7 @@ substitutions = \
        '|udevlibexecdir=$(udevlibexecdir)|' \
        '|KILL=$(KILL)|' \
        '|MKDIR_P=$(MKDIR_P)|' \
+       '|KILL_USER_PROCESSES=$(KILL_USER_PROCESSES)|' \
        '|systemuidmax=$(SYSTEM_UID_MAX)|' \
        '|systemgidmax=$(SYSTEM_GID_MAX)|' \
        '|TTY_GID=$(TTY_GID)|'
@@ -973,7 +1038,6 @@ DISTCHECK_CONFIGURE_FLAGS += \
 endif
 
 .PHONY: dist-check-help
-
 dist-check-help: $(rootbin_PROGRAMS)
        for i in $(abspath $^); do                                             \
             if $$i  --help | grep -v 'default:' | grep -E -q '.{80}.' ; then   \
@@ -982,6 +1046,18 @@ dist-check-help: $(rootbin_PROGRAMS)
                exit 1;                                                        \
             fi; done
 
+include_compilers = "$(CC)" "$(CC) -ansi" "$(CC) -std=iso9899:1990"
+public_headers = $(filter-out src/systemd/_sd-common.h, $(pkginclude_HEADERS) $(include_HEADERS))
+.PHONY: dist-check-includes
+dist-check-includes: $(public_headers)
+       @res=0;                                                                 \
+       for i in $(abspath $^); do                                              \
+           for cc in $(include_compilers); do                                  \
+               echo "$$cc -o/dev/null -c -x c -include "$$i" - </dev/null";    \
+               $$cc -o/dev/null -c -x c -include "$$i" - </dev/null || res=1;  \
+           done;                                                               \
+       done; exit $$res
+
 dist:
 
 .PHONY: git-tag
@@ -1030,7 +1106,7 @@ install-tree: all
 .PHONY: valgrind-tests
 valgrind-tests: $(TESTS)
        $(AM_V_GEN)for f in $(filter-out %.pl, $^); do \
-               if file $$f | grep -q shell; then \
+               if $(LIBTOOL) --mode=execute file $$f | grep -q shell; then \
                echo -e "$${x}Skipping non-binary $$f"; else \
                echo -e "$${x}Running $$f"; \
                libtool --mode=execute valgrind -q --leak-check=full --max-stackframe=5242880 --error-exitcode=55 $(builddir)/$$f ; fi; \
diff --git a/NEWS b/NEWS
index e7f6bb45933e839d21acabd5345ee3fb800498b3..ca54685878ff3ec15f3f6b8469ba6b9df2a84a55 100644 (file)
--- a/NEWS
+++ b/NEWS
 systemd System and Service Manager
 
+CHANGES WITH 231:
+
+        * In service units the various ExecXYZ= settings have been extended
+          with an additional special character as first argument of the
+          assigned value: if the character '+' is used the specified command
+          line it will be run with full privileges, regardless of User=,
+          Group=, CapabilityBoundingSet= and similar options. The effect is
+          similar to the existing PermissionsStartOnly= option, but allows
+          configuration of this concept for each executed command line
+          independently.
+
+        * Services may now alter the service watchdog timeout at runtime by
+          sending a WATCHDOG_USEC= message via sd_notify().
+
+        * MemoryLimit= and related unit settings now optionally take percentage
+          specifications. The percentage is taken relative to the amount of
+          physical memory in the system (or in case of containers, the assigned
+          amount of memory). This allows scaling service resources neatly with
+          the amount of RAM available on the system. Similarly, systemd-logind's
+          RuntimeDirectorySize= option now also optionally takes percentage
+          values.
+
+        * In similar fashion TasksMax= takes percentage values now, too. The
+          value is taken relative to the configured maximum number of processes
+          on the system. The per-service task maximum has been changed to 15%
+          using this functionality. (Effectively this is an increase of 512 →
+          4915 for service units, given the kernel's default pid_max setting.)
+
+        * Calendar time specifications in .timer units now understand a ".."
+          syntax for time ranges. Example: "4..7:10" may now be used for
+          defining a timer that is triggered at 4:10am, 5:10am, 6:10am and
+          7:10am every day.
+
+        * The InaccessableDirectories=, ReadOnlyDirectories= and
+          ReadWriteDirectories= unit file settings have been renamed to
+          InaccessablePaths=, ReadOnlyPaths= and ReadWritePaths= and may now be
+          applied to all kinds of file nodes, and not just directories, with
+          the exception of symlinks. Specifically these settings may now be
+          used on block and character device nodes, UNIX sockets and FIFOS as
+          well as regular files. The old names of these settings remain
+          available for compatibility.
+
+        * systemd will now log about all service processes it kills forcibly
+          (using SIGKILL) because they remained after the clean shutdown phase
+          of the service completed. This should help identifying services that
+          shut down uncleanly. Moreover if KillUserProcesses= is enabled in
+          systemd-logind's configuration a similar log message is generated for
+          processes killed at the end of each session due to this setting.
+
+        * systemd will now set the $JOURNAL_STREAM environment variable for all
+          services whose stdout/stderr are connected to the Journal (which
+          effectively means by default: all services). The variable contains
+          the device and inode number of the file descriptor used for
+          stdout/stderr. This may be used by invoked programs to detect whether
+          their stdout/stderr is connected to the Journal, in which case they
+          can switch over to direct Journal communication, thus being able to
+          pass extended, structured metadata along with their log messages. As
+          one example, this is now used by glib's logging primitives.
+
+        * When using systemd's default tmp.mount unit for /tmp, the mount point
+          will now be established with the "nosuid" and "nodev" options. This
+          avoids privilege escalation attacks that put traps and exploits into
+          /tmp.  However, this might cause problems if you e. g. put container
+          images or overlays into /tmp; if you need this, override tmp.mount's
+          "Options=" with a drop-in, or mount /tmp from /etc/fstab with your
+          desired options.
+
+        * systemd now supports the "memory" cgroup controller also on
+          cgroupsv2.
+
+        * The systemd-cgtop tool now optionally takes a control group path as
+          command line argument. If specified, the control group list shown is
+          limited to subgroups of that group.
+
+        * The SystemCallFilter= unit file setting gained support for
+          pre-defined, named system call filter sets. For example
+          SystemCallFilter=@clock is now an effective way to make all clock
+          changing-related system calls unavailable to a service. A number of
+          similar pre-defined groups are defined. Writing system call filters
+          for system services is simplified substantially with this new
+          concept. Accordingly, all of systemd's own, long-running services now
+          enable system call filtering based on this, by default.
+
+        * A new service setting MemoryDenyWriteExecute= has been added, taking
+          a boolean value. If turned on, a service may no longer create memory
+          mappings that are writable and executable at the same time. This
+          enhances security for services where this is enabled as it becomes
+          harder to dynamically write and then execute memory in exploited
+          service processes. This option has been enabled for all of systemd's
+          own long-running services.
+
+        * A new RestrictRealtime= service setting has been added, taking a
+          boolean argument. If set the service's processes may no longer
+          acquire realtime scheduling. This improves security as realtime
+          scheduling may otherwise be used to easily freeze the system.
+
+        * systemd-nspawn gained a new switch --notify-ready= taking a boolean
+          value. This may be used for requesting that the system manager inside
+          of the container reports start-up completion to nspawn which then
+          propagates this notification further to the service manager
+          supervising nspawn itself. A related option NotifyReady= in .nspawn
+          files has been added too. This functionality allows ordering of the
+          start-up of multiple containers using the usual systemd ordering
+          primitives.
+
+        * machinectl gained a new command "stop" that is an alias for
+          "terminate".
+
+        * systemd-resolved gained support for contacting DNS servers on
+          link-local IPv6 addresses.
+
+        * If systemd-resolved receives the SIGUSR2 signal it will now flush all
+          its caches. A method call for requesting the same operation has been
+          added to the bus API too, and is made available via "systemd-resolve
+          --flush-caches".
+
+        * systemd-resolve gained a new --status switch. If passed a brief
+          summary of the used DNS configuration with per-interface information
+          is shown.
+
+        * resolved.conf gained a new Cache= boolean option, defaulting to
+          on. If turned off local DNS caching is disabled. This comes with a
+          performance penalty in particular when DNSSEC is enabled. Note that
+          resolved disables its internal caching implicitly anyway, when the
+          configured DNS server is on a host-local IP address such as ::1 or
+          127.0.0.1, thus automatically avoiding double local caching.
+
+        * systemd-resolved now listens on the local IP address 127.0.0.53:53
+          for DNS requests. This improves compatibility with local programs
+          that do not use the libc NSS or systemd-resolved's bus APIs for name
+          resolution. This minimal DNS service is only available to local
+          programs and does not implement the full DNS protocol, but enough to
+          cover local DNS clients. A new, static resolv.conf file, listing just
+          this DNS server is now shipped in /usr/lib/systemd/resolv.conf. It is
+          now recommended to make /etc/resolv.conf a symlink to this file in
+          order to route all DNS lookups to systemd-resolved, regardless if
+          done via NSS, the bus API or raw DNS packets. Note that this local
+          DNS service is not as fully featured as the libc NSS or
+          systemd-resolved's bus APIs. For example, as unicast DNS cannot be
+          used to deliver link-local address information (as this implies
+          sending a local interface index along), LLMNR/mDNS support via this
+          interface is severely restricted. It is thus strongly recommended for
+          all applications to use the libc NSS API or native systemd-resolved
+          bus API instead.
+
+        * systemd-networkd's bridge support learned a new setting
+          VLANFiltering= for controlling VLAN filtering. Moreover a new section
+          in .network files has been added for configuring VLAN bridging in
+          more detail: VLAN=, EgressUntagged=, PVID= in [BridgeVLAN].
+
+        * systemd-networkd's IPv6 Router Advertisement code now makes use of
+          the DNSSL and RDNSS options. This means IPv6 DNS configuration may
+          now be acquired without relying on DHCPv6. Two new options
+          UseDomains= and UseDNS= have been added to configure this behaviour.
+
+        * systemd-networkd's IPv6AcceptRouterAdvertisements= option has been
+          renamed IPv6AcceptRA=, without altering its behaviour. The old
+          setting name remains available for compatibility reasons.
+
+        * The systemd-networkd VTI/VTI6 tunneling support gained new options
+          Key=, InputKey= and OutputKey=.
+
+        * systemd-networkd gained support for VRF ("Virtual Routing Function")
+          interface configuration.
+
+        * "systemctl edit" may now be used to create new unit files by
+          specifying the --force switch.
+
+        * sd-event gained a new function sd_event_get_iteration() for
+          requesting the current iteration counter of the event loop. It starts
+          at zero and is increased by one with each event loop iteration.
+
+        * A new rpm macro %systemd_ordering is provided by the macros.systemd
+          file. It can be used in lieu of %systemd_requires in packages which
+          don't use any systemd functionality and are intended to be installed
+          in minimal containers without systemd present. This macro provides
+          ordering dependecies to ensure that if the package is installed in
+          the same rpm transaction as systemd, systemd will be installed before
+          the scriptlets for the package are executed, allowing unit presets
+          to be handled.
+
+          New macros %_systemdgeneratordir and %_systemdusergeneratordir have
+          been added to simplify packaging of generators.
+
+        * The os-release file gained VERSION_CODENAME field for the
+          distribution nickname (e.g. VERSION_CODENAME=woody).
+
+        * New udev property UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG=1
+          can be set to disable parsing of metadata and the creation
+          of persistent symlinks for that device.
+
+        * The v230 change to tag framebuffer devices (/dev/fb*) with "uaccess"
+          to make them available to logged-in users has been reverted.
+
+        * Much of the common code of the various systemd components is now
+          built into an internal shared library libsystemd-shared-231.so
+          (incorporating the systemd version number in the name, to be updated
+          with future releases) that the components link to. This should
+          decrease systemd footprint both in memory during runtime and on
+          disk. Note that the shared library is not for public use, and is
+          neither API not ABI stable, but is likely to change with every new
+          released update. Packagers need to make sure that binaries
+          linking to libsystemd-shared.so are updated in step with the
+          library.
+
+        * Configuration for "mkosi" is now part of the systemd
+          repository. mkosi is a tool to easily build legacy-free OS images,
+          and is available on github: https://github.com/systemd/mkosi. If
+          "mkosi" is invoked in the build tree a new raw OS image is generated
+          incorporating the systemd sources currently being worked on and a
+          clean, fresh distribution installation. The generated OS image may be
+          booted up with "systemd-nspawn -b -i", qemu-kvm or on any physcial
+          UEFI PC. This functionality is particularly useful to easily test
+          local changes made to systemd in a pristine, defined environment. See
+          HACKING for details.
+
+        Contributions from: Alban Crequy, Alessandro Puccetti, Alessio Igor
+        Bogani, Alexander Kuleshov, Alexander Kurtz, Alex Gaynor, Andika
+        Triwidada, Andreas Pokorny, Andreas Rammhold, Andrew Jeddeloh, Ansgar
+        Burchardt, Atrotors, Benjamin Drung, Brian Boylston, Christian Hesse,
+        Christian Rebischke, Daniele Medri, Daniel Mack, Dave Reisner, David
+        Herrmann, David Michael, Djalal Harouni, Douglas Christman, Elias
+        Probst, Evgeny Vereshchagin, Federico Mena Quintero, Felipe Sateler,
+        Franck Bui, Harald Hoyer, Ian Lee, Ivan Shapovalov, Jakub Wilk, Jan
+        Janssen, Jean-Sébastien Bour, John Paul Adrian Glaubitz, Jouke
+        Witteveen, Kai Ruhnau, kpengboy, Kyle Walker, Lénaïc Huard, Lennart
+        Poettering, Luca Bruno, Lukas Lösche, Lukáš Nykrýn, mahkoh, Marcel
+        Holtmann, Martin Pitt, Marty Plummer, Matthieu Codron, Max Prokhorov,
+        Michael Biebl, Michael Karcher, Michael Olbrich, Michał Bartoszkiewicz,
+        Michal Sekletar, Michal Soltys, Minkyung, Muhammet Kara, mulkieran,
+        Otto Wallenius, Pablo Lezaeta Reyes, Peter Hutterer, Ronny Chevalier,
+        Rusty Bird, Stef Walter, Susant Sahani, Tejun Heo, Thomas Blume, Thomas
+        Haller, Thomas H. P. Andersen, Tobias Jungel, Tom Gundersen, Tom Yan,
+        Topi Miettinen, Torstein Husebø, Valentin Vidić, Viktar Vaŭčkievič,
+        WaLyong Cho, Weng Xuetian, Werner Fink, Zbigniew Jędrzejewski-Szmek
+
+        — Berlin, 2016-07-25
+
+CHANGES WITH 230:
+
+        * DNSSEC is now turned on by default in systemd-resolved (in
+          "allow-downgrade" mode), but may be turned off during compile time by
+          passing "--with-default-dnssec=no" to "configure" (and of course,
+          during runtime with DNSSEC= in resolved.conf). We recommend
+          downstreams to leave this on at least during development cycles and
+          report any issues with the DNSSEC logic upstream. We are very
+          interested in collecting feedback about the DNSSEC validator and its
+          limitations in the wild. Note however, that DNSSEC support is
+          probably nothing downstreams should turn on in stable distros just
+          yet, as it might create incompatibilities with a few DNS servers and
+          networks. We tried hard to make sure we downgrade to non-DNSSEC mode
+          automatically whenever we detect such incompatible setups, but there
+          might be systems we do not cover yet. Hence: please help us testing
+          the DNSSEC code, leave this on where you can, report back, but then
+          again don't consider turning this on in your stable, LTS or
+          production release just yet. (Note that you have to enable
+          nss-resolve in /etc/nsswitch.conf, to actually use systemd-resolved
+          and its DNSSEC mode for host name resolution from local
+          applications.)
+
+        * systemd-resolve conveniently resolves DANE records with the --tlsa
+          option and OPENPGPKEY records with the --openpgp option. It also
+          supports dumping raw DNS record data via the new --raw= switch.
+
+        * systemd-logind will now by default terminate user processes that are
+          part of the user session scope unit (session-XX.scope) when the user
+          logs out. This behavior is controlled by the KillUserProcesses=
+          setting in logind.conf, and the previous default of "no" is now
+          changed to "yes". This means that user sessions will be properly
+          cleaned up after, but additional steps are necessary to allow
+          intentionally long-running processes to survive logout.
+
+          While the user is logged in at least once, user@.service is running,
+          and any service that should survive the end of any individual login
+          session can be started at a user service or scope using systemd-run.
+          systemd-run(1) man page has been extended with an example which shows
+          how to run screen in a scope unit underneath user@.service. The same
+          command works for tmux.
+
+          After the user logs out of all sessions, user@.service will be
+          terminated too, by default, unless the user has "lingering" enabled.
+          To effectively allow users to run long-term tasks even if they are
+          logged out, lingering must be enabled for them. See loginctl(1) for
+          details. The default polkit policy was modified to allow users to
+          set lingering for themselves without authentication.
+
+          Previous defaults can be restored at compile time by the
+          --without-kill-user-processes option to "configure".
+
+        * systemd-logind gained new configuration settings SessionsMax= and
+          InhibitorsMax=, both with a default of 8192. It will not register new
+          user sessions or inhibitors above this limit.
+
+        * systemd-logind will now reload configuration on SIGHUP.
+
+        * The unified cgroup hierarchy added in Linux 4.5 is now supported.
+          Use systemd.unified_cgroup_hierarchy=1 on the kernel command line to
+          enable. Also, support for the "io" cgroup controller in the unified
+          hierarchy has been added, so that the "memory", "pids" and "io" are
+          now the controllers that are supported on the unified hierarchy.
+
+          WARNING: it is not possible to use previous systemd versions with
+          systemd.unified_cgroup_hierarchy=1 and the new kernel. Therefore it
+          is necessary to also update systemd in the initramfs if using the
+          unified hierarchy. An updated SELinux policy is also required.
+
+        * LLDP support has been extended, and both passive (receive-only) and
+          active (sender) modes are supported. Passive mode ("routers-only") is
+          enabled by default in systemd-networkd. Active LLDP mode is enabled
+          by default for containers on the internal network. The "networkctl
+          lldp" command may be used to list information gathered. "networkctl
+          status" will also show basic LLDP information on connected peers now.
+
+        * The IAID and DUID unique identifier sent in DHCP requests may now be
+          configured for the system and each .network file managed by
+          systemd-networkd using the DUIDType=, DUIDRawData=, IAID= options.
+
+        * systemd-networkd gained support for configuring proxy ARP support for
+          each interface, via the ProxyArp= setting in .network files. It also
+          gained support for configuring the multicast querier feature of
+          bridge devices, via the new MulticastQuerier= setting in .netdev
+          files. Similarly, snooping on the IGMP traffic can be controlled
+          via the new setting MulticastSnooping=.
+
+          A new setting PreferredLifetime= has been added for addresses
+          configured in .network file to configure the lifetime intended for an
+          address.
+
+          The systemd-networkd DHCP server gained the option EmitRouter=, which
+          defaults to yes, to configure whether the DHCP Option 3 (Router)
+          should be emitted.
+
+        * The testing tool /usr/lib/systemd/systemd-activate is renamed to
+          systemd-socket-activate and installed into /usr/bin. It is now fully
+          supported.
+
+        * systemd-journald now uses separate threads to flush changes to disk
+          when closing journal files, thus reducing impact of slow disk I/O on
+          logging performance.
+
+        * The sd-journal API gained two new calls
+          sd_journal_open_directory_fd() and sd_journal_open_files_fd() which
+          can be used to open journal files using file descriptors instead of
+          file or directory paths. sd_journal_open_container() has been
+          deprecated, sd_journal_open_directory_fd() should be used instead
+          with the flag SD_JOURNAL_OS_ROOT.
+
+        * journalctl learned a new output mode "-o short-unix" that outputs log
+          lines prefixed by their UNIX time (i.e. seconds since Jan 1st, 1970
+          UTC). It also gained support for a new --no-hostname setting to
+          suppress the hostname column in the family of "short" output modes.
+
+        * systemd-ask-password now optionally skips printing of the password to
+          stdout with --no-output which can be useful in scripts.
+
+        * Framebuffer devices (/dev/fb*) and 3D printers and scanners
+          (devices tagged with ID_MAKER_TOOL) are now tagged with
+          "uaccess" and are available to logged in users.
+
+        * The DeviceAllow= unit setting now supports specifiers (with "%").
+
+        * "systemctl show" gained a new --value switch, which allows print a
+          only the contents of a specific unit property, without also printing
+          the property's name. Similar support was added to "show*" verbs
+          of loginctl and machinectl that output "key=value" lists.
+
+        * A new unit type "generated" was added for files dynamically generated
+          by generator tools. Similarly, a new unit type "transient" is used
+          for unit files created using the runtime API. "systemctl enable" will
+          refuse to operate on such files.
+
+        * A new command "systemctl revert" has been added that may be used to
+          revert to the vendor version of a unit file, in case local changes
+          have been made by adding drop-ins or overriding the unit file.
+
+        * "machinectl clean" gained a new verb to automatically remove all or
+          just hidden container images.
+
+        * systemd-tmpfiles gained support for a new line type "e" for emptying
+          directories, if they exist, without creating them if they don't.
+
+        * systemd-nspawn gained support for automatically patching the UID/GIDs
+          of the owners and the ACLs of all files and directories in a
+          container tree to match the UID/GID user namespacing range selected
+          for the container invocation. This mode is enabled via the new
+          --private-user-chown switch. It also gained support for automatically
+          choosing a free, previously unused UID/GID range when starting a
+          container, via the new --private-users=pick setting (which implies
+          --private-user-chown). Together, these options for the first time
+          make user namespacing for nspawn containers fully automatic and thus
+          deployable. The systemd-nspawn@.service template unit file has been
+          changed to use this functionality by default.
+
+        * systemd-nspawn gained a new --network-zone= switch, that allows
+          creating ad-hoc virtual Ethernet links between multiple containers,
+          that only exist as long as at least one container referencing them is
+          running. This allows easy connecting of multiple containers with a
+          common link that implements an Ethernet broadcast domain. Each of
+          these network "zones" may be named relatively freely by the user, and
+          may be referenced by any number of containers, but each container may
+          only reference one of these "zones". On the lower level, this is
+          implemented by an automatically managed bridge network interface for
+          each zone, that is created when the first container referencing its
+          zone is created and removed when the last one referencing its zone
+          terminates.
+
+        * The default start timeout may now be configured on the kernel command
+          line via systemd.default_timeout_start_sec=. It was already
+          configurable via the DefaultTimeoutStartSec= option in
+          /etc/systemd/system.conf.
+
+        * Socket units gained a new TriggerLimitIntervalSec= and
+          TriggerLimitBurst= setting to configure a limit on the activation
+          rate of the socket unit.
+
+        * The LimitNICE= setting now optionally takes normal UNIX nice values
+          in addition to the raw integer limit value. If the specified
+          parameter is prefixed with "+" or "-" and is in the range -20..19 the
+          value is understood as UNIX nice value. If not prefixed like this it
+          is understood as raw RLIMIT_NICE limit.
+
+        * Note that the effect of the PrivateDevices= unit file setting changed
+          slightly with this release: the per-device /dev file system will be
+          mounted read-only from this version on, and will have "noexec"
+          set. This (minor) change of behavior might cause some (exceptional)
+          legacy software to break, when PrivateDevices=yes is set for its
+          service. Please leave PrivateDevices= off if you run into problems
+          with this.
+
+        * systemd-bootchart has been split out to a separate repository:
+          https://github.com/systemd/systemd-bootchart
+
+        * systemd-bus-proxyd has been removed, as kdbus is unlikely to still be
+          merged into the kernel in its current form.
+
+        * The compatibility libraries libsystemd-daemon.so,
+          libsystemd-journal.so, libsystemd-id128.so, and libsystemd-login.so
+          which have been deprecated since systemd-209 have been removed along
+          with the corresponding pkg-config files. All symbols provided by
+          those libraries are provided by libsystemd.so.
+
+        * The Capabilities= unit file setting has been removed (it is ignored
+          for backwards compatibility). AmbientCapabilities= and
+          CapabilityBoundingSet= should be used instead.
+
+        * A new special target has been added, initrd-root-device.target,
+          which creates a synchronization point for dependencies of the root
+          device in early userspace. Initramfs builders must ensure that this
+          target is now included in early userspace.
+
+        Contributions from: Alban Crequy, Alexander Kuleshov, Alexander Shopov,
+        Alex Crawford, Andre Klärner, Andrew Eikum, Beniamino Galvani, Benjamin
+        Robin, Biao Lu, Bjørnar Ness, Calvin Owens, Christian Hesse, Clemens
+        Gruber, Colin Guthrie, Daniel Drake, Daniele Medri, Daniel J Walsh,
+        Daniel Mack, Dan Nicholson, daurnimator, David Herrmann, David
+        R. Hedges, Elias Probst, Emmanuel Gil Peyrot, EMOziko, Evgeny
+        Vereshchagin, Federico, Felipe Sateler, Filipe Brandenburger, Franck
+        Bui, frankheckenbach, gdamjan, Georgia Brikis, Harald Hoyer, Hendrik
+        Brueckner, Hristo Venev, Iago López Galeiras, Ian Kelling, Ismo
+        Puustinen, Jakub Wilk, Jaroslav Škarvada, Jeff Huang, Joel Holdsworth,
+        John Paul Adrian Glaubitz, Jonathan Boulle, kayrus, Klearchos
+        Chaloulos, Kyle Russell, Lars Uebernickel, Lennart Poettering, Lubomir
+        Rintel, Lukáš Nykrýn, Mantas Mikulėnas, Marcel Holtmann, Martin Pitt,
+        Michael Biebl, michaelolbrich, Michał Bartoszkiewicz, Michal Koutný,
+        Michal Sekletar, Mike Frysinger, Mike Gilbert, Mingcong Bai, Ming Lin,
+        mulkieran, muzena, Nalin Dahyabhai, Naohiro Aota, Nathan McSween,
+        Nicolas Braud-Santoni, Patrik Flykt, Peter Hutterer, Peter Mattern,
+        Petr Lautrbach, Petros Angelatos, Piotr Drąg, Rabin Vincent, Robert
+        Węcławski, Ronny Chevalier, Samuel Tardieu, Stefan Saraev, Stefan
+        Schallenberg aka nafets227, Steven Siloti, Susant Sahani, Sylvain
+        Plantefève, Taylor Smock, Tejun Heo, Thomas Blume, Thomas Haller,
+        Thomas H. P. Andersen, Tobias Klauser, Tom Gundersen, topimiettinen,
+        Torstein Husebø, Umut Tezduyar Lindskog, Uwe Kleine-König, Victor Toso,
+        Vinay Kulkarni, Vito Caputo, Vittorio G (VittGam), Vladimir Panteleev,
+        Wieland Hoffmann, Wouter Verhelst, Yu Watanabe, Zbigniew
+        Jędrzejewski-Szmek
+
+        — Fairfax, 2016-05-21
+
 CHANGES WITH 229:
 
         * The systemd-resolved DNS resolver service has gained a substantial
           set of new features, most prominently it may now act as a DNSSEC
           validating stub resolver. DNSSEC mode is currently turned off by
-          default, but it is expected that this is turned on by default in one
-          of the next releases. For now, we invite everybody to test the DNSSEC
-          logic by setting DNSSEC=allow-downgrade in
-          /etc/systemd/resolved.conf. The service also gained a full set of
-          D-Bus interfaces, including calls to configure DNS and DNSSEC
-          settings per link (for consumption by external network management
-          software). systemd-resolved (and systemd-networkd along with it) now
-          know to distinguish between "search" and "routing" domains. The
-          former are used to qualify single-label names, the latter are purely
-          used for routing lookups within certain domains to specific
-          links. resolved will now also synthesize RRs for all entries from
-          /etc/hosts.
+          default, but is expected to be turned on by default in one of the
+          next releases. For now, we invite everybody to test the DNSSEC logic
+          by setting DNSSEC=allow-downgrade in /etc/systemd/resolved.conf. The
+          service also gained a full set of D-Bus interfaces, including calls
+          to configure DNS and DNSSEC settings per link (for use by external
+          network management software). systemd-resolved and systemd-networkd
+          now distinguish between "search" and "routing" domains. The former
+          are used to qualify single-label names, the latter are used purely
+          for routing lookups within certain domains to specific links.
+          resolved now also synthesizes RRs for all entries from /etc/hosts.
 
         * The systemd-resolve tool (which is a client utility for
-          systemd-resolved, and previously experimental) has been improved
-          considerably and is now fully supported and documented. Hence it has
-          moved from /usr/lib/systemd to /usr/bin.
+          systemd-resolved) has been improved considerably and is now fully
+          supported and documented. Hence it has moved from /usr/lib/systemd to
+          /usr/bin.
 
         * /dev/disk/by-path/ symlink support has been (re-)added for virtio
           devices.
@@ -80,22 +557,22 @@ CHANGES WITH 229:
 
         * systemd-nspawn gained a new --as-pid2 switch that invokes any
           specified command line as PID 2 rather than PID 1 in the
-          container. In this mode PID 1 will be a minimal stub init process
-          that implements the special POSIX and Linux semantics of PID 1
-          regarding signal and child process management. Note that this stub
-          init process is implemented in nspawn itself and requires no support
-          from the container image. This new logic is useful to support running
-          arbitrary command lines in the container, as normal processes are
+          container. In this mode PID 1 is a minimal stub init process that
+          implements the special POSIX and Linux semantics of PID 1 regarding
+          signal and child process management. Note that this stub init process
+          is implemented in nspawn itself and requires no support from the
+          container image. This new logic is useful to support running
+          arbitrary commands in the container, as normal processes are
           generally not prepared to run as PID 1.
 
         * systemd-nspawn gained a new --chdir= switch for setting the current
           working directory for the process started in the container.
 
-        * "journalctl /dev/sda" will now output all kernel log messages from
-          the specified device, in addition to all devices that are parents of
-          it. This should make log output about devices pretty useful, as long
-          as kernel drivers attach enough metadata to the log messages. (The
-          usual SATA drivers do.)
+        * "journalctl /dev/sda" will now output all kernel log messages for
+          specified device from the current boot, in addition to all devices
+          that are parents of it. This should make log output about devices
+          pretty useful, as long as kernel drivers attach enough metadata to
+          the log messages. (The usual SATA drivers do.)
 
         * The sd-journal API gained two new calls
           sd_journal_has_runtime_files() and sd_journal_has_persistent_files()
@@ -125,7 +602,7 @@ CHANGES WITH 229:
           in addition to timesyncd during early boot-up, so that it is enforced
           before the first process is spawned by systemd. Note that the logic
           in timesyncd remains, as it is more comprehensive and ensures
-          montonic clocks by maintaining a persistant timestamp file in
+          clock monotonicity by maintaining a persistent timestamp file in
           /var. Since /var is generally not available in earliest boot or the
           initrd, this part of the logic remains in timesyncd, and is not done
           by PID 1.
@@ -154,18 +631,18 @@ CHANGES WITH 229:
           to configure hard and soft limits individually.
 
         * The various libsystemd APIs such as sd-bus or sd-event now publicly
-          expose support for gcc's __attribute__((cleanup())) C
-          extension. Specifically, for many object destructor functions
-          alternative versions whose names are suffixed with "p" have been
-          added, which take a pointer to a pointer to the object to destroy,
-          instead of just a pointer to the object itself. This is useful because
-          these destructor functions may be used directly as parameters to the
-          cleanup construct. Internally, systemd has been a heavy user of the
-          GCC extension since a long time, and with this change similar support
-          is now available to consumers of the library outside of systemd. Note
+          expose support for gcc's __attribute__((cleanup())) C extension.
+          Specifically, for many object destructor functions alternative
+          versions have been added that have names suffixed with "p" and take a
+          pointer to a pointer to the object to destroy, instead of just a
+          pointer to the object itself. This is useful because these destructor
+          functions may be used directly as parameters to the cleanup
+          construct. Internally, systemd has been a heavy user of this GCC
+          extension for a long time, and with this change similar support is
+          now available to consumers of the library outside of systemd. Note
           that by using this extension in your sources compatibility with old
-          and strictly ANSI compatible C compilers is lost. However, any gcc or
-          LLVM version of recent years have supported this extension.
+          and strictly ANSI compatible C compilers is lost. However, all gcc or
+          LLVM versions of recent years support this extension.
 
         * Timer units gained support for a new setting RandomizedDelaySec= that
           allows configuring some additional randomized delay to the configured
@@ -217,7 +694,7 @@ CHANGES WITH 229:
         Andersen, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Vito
         Caputo, WaLyong Cho, Yu Watanabe, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2016-02-11
+         Berlin, 2016-02-11
 
 CHANGES WITH 228:
 
@@ -308,7 +785,7 @@ CHANGES WITH 228:
           the service.
 
         * Timer units gained support for a new RemainAfterElapse=
-          setting which takes a boolean argument. It defaults on on,
+          setting which takes a boolean argument. It defaults to on,
           exposing behaviour unchanged to previous releases. If set to
           off, timer units are unloaded after they elapsed if they
           cannot elapse again. This is particularly useful for
@@ -348,6 +825,9 @@ CHANGES WITH 228:
 
           https://sourceware.org/bugzilla/show_bug.cgi?id=19108
 
+          Note that only util-linux versions built with
+          --enable-libmount-force-mountinfo are supported.
+
         * Support for the ".snapshot" unit type has been removed. This
           feature turned out to be little useful and little used, and
           has now been removed from the core and from systemctl.
@@ -415,7 +895,7 @@ CHANGES WITH 228:
         Tom Gundersen, Torstein Husebø, Vito Caputo, Zbigniew
         Jędrzejewski-Szmek
 
-        -- Berlin, 2015-11-18
+         Berlin, 2015-11-18
 
 CHANGES WITH 227:
 
@@ -496,7 +976,7 @@ CHANGES WITH 227:
         * Support for USB FunctionFS activation has been added. This
           allows implementation of USB gadget services that are
           activated as soon as they are requested, so that they don't
-          have to run continously, similar to classic socket
+          have to run continuously, similar to classic socket
           activation.
 
         * The "systemctl exit" command now optionally takes an
@@ -541,7 +1021,7 @@ CHANGES WITH 227:
 
         * systemd-networkd gained support for:
 
-            - Setting the IPv6 Router Advertisment settings via
+            - Setting the IPv6 Router Advertisement settings via
               IPv6AcceptRouterAdvertisements= in .network files.
 
             - Configuring the HelloTimeSec=, MaxAgeSec= and
@@ -587,7 +1067,7 @@ CHANGES WITH 227:
           files controlled by the number of files that shall remain,
           in addition to the already existing control by size and by
           date. This is useful as journal interleaving performance
-          degrades with too many seperate journal files, and allows
+          degrades with too many separate journal files, and allows
           putting an effective limit on them. The new setting defaults
           to 100, but this may be changed by setting SystemMaxFiles=
           and RuntimeMaxFiles= in journald.conf. Also, the
@@ -619,7 +1099,7 @@ CHANGES WITH 227:
         Andersen, Tom Gundersen, Tom Lyon, Viktar Vauchkevich,
         Zbigniew Jędrzejewski-Szmek, Марко М. Костић
 
-        -- Berlin, 2015-10-07
+         Berlin, 2015-10-07
 
 CHANGES WITH 226:
 
@@ -674,7 +1154,7 @@ CHANGES WITH 226:
           available, systemd will fall back to the legacy cgroup
           hierarchy setup, as before. Host system and containers can
           mix and match legacy and unified hierarchies as they
-          wish. nspawn understands the $UNIFIED_CROUP_HIERARCHY
+          wish. nspawn understands the $UNIFIED_CGROUP_HIERARCHY
           environment variable to individually select the hierarchy to
           use for executed containers. By default, nspawn will use the
           unified hierarchy for the containers if the host uses the
@@ -739,7 +1219,7 @@ CHANGES WITH 226:
         Hack, Susant Sahani, Sylvain Pasche, Thomas Hindoe Paaboel
         Andersen, Tom Gundersen, Torstein Husebø
 
-        -- Berlin, 2015-09-08
+         Berlin, 2015-09-08
 
 CHANGES WITH 225:
 
@@ -812,7 +1292,7 @@ CHANGES WITH 225:
         Paaboel Andersen, Thomas Meyer, Tom Gundersen, Vincent Batts,
         WaLyong Cho, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2015-08-27
+         Berlin, 2015-08-27
 
 CHANGES WITH 224:
 
@@ -827,7 +1307,7 @@ CHANGES WITH 224:
         Herrmann, Herman Fries, Johannes Nixdorf, Kay Sievers, Lennart
         Poettering, Peter Hutterer, Susant Sahani, Tom Gundersen
 
-        -- Berlin, 2015-07-31
+         Berlin, 2015-07-31
 
 CHANGES WITH 223:
 
@@ -892,7 +1372,7 @@ CHANGES WITH 223:
         Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Vito Caputo,
         Vivenzio Pagliari, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2015-07-29
+         Berlin, 2015-07-29
 
 CHANGES WITH 222:
 
@@ -932,7 +1412,7 @@ CHANGES WITH 222:
         Susant Sahani, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein
         Husebø, Vedran Miletić, WaLyong Cho, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2015-07-07
+         Berlin, 2015-07-07
 
 CHANGES WITH 221:
 
@@ -1010,7 +1490,7 @@ CHANGES WITH 221:
         Husebø, Umut Tezduyar Lindskog, Viktar Vauchkevich, Werner
         Fink, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2015-06-19
+         Berlin, 2015-06-19
 
 CHANGES WITH 220:
 
@@ -1239,7 +1719,7 @@ CHANGES WITH 220:
         Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Will
         Woods, Zachary Cook, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2015-05-22
+         Berlin, 2015-05-22
 
 CHANGES WITH 219:
 
@@ -1324,7 +1804,7 @@ CHANGES WITH 219:
 
         * machinectl is now able to clone container images
           efficiently, if the underlying file system (btrfs) supports
-          it, with the new "machinectl list-images" command. It also
+          it, with the new "machinectl clone" command. It also
           gained commands for renaming and removing images, as well as
           marking them read-only or read-write (supported also on
           legacy file systems).
@@ -1563,7 +2043,7 @@ CHANGES WITH 219:
         Lindskog, Veres Lajos, Vincent Batts, WaLyong Cho, Wieland
         Hoffmann, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2015-02-16
+         Berlin, 2015-02-16
 
 CHANGES WITH 218:
 
@@ -1765,7 +2245,7 @@ CHANGES WITH 218:
         Torstein Husebø, Umut Tezduyar Lindskog, Vicente Olivert
         Riera, WaLyong Cho, Wesley Dawson, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2014-12-10
+         Berlin, 2014-12-10
 
 CHANGES WITH 217:
 
@@ -1977,7 +2457,7 @@ CHANGES WITH 217:
         Husebø, Umut Tezduyar Lindskog, WaLyong Cho, Zbigniew
         Jędrzejewski-Szmek
 
-        -- Berlin, 2014-10-28
+         Berlin, 2014-10-28
 
 CHANGES WITH 216:
 
@@ -2179,7 +2659,7 @@ CHANGES WITH 216:
         Tobias Geerinckx-Rice, Tomasz Torcz, Tom Gundersen, Umut
         Tezduyar Lindskog, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2014-08-19
+         Berlin, 2014-08-19
 
 CHANGES WITH 215:
 
@@ -2413,7 +2893,7 @@ CHANGES WITH 215:
         Paaboel Andersen, Tom Gundersen, Tom Hirst, Umut Tezduyar
         Lindskog, Uoti Urpala, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2014-07-03
+         Berlin, 2014-07-03
 
 CHANGES WITH 214:
 
@@ -2607,7 +3087,7 @@ CHANGES WITH 214:
         Andersen, Tom Gundersen, Umut Tezduyar Lindskog, Zbigniew
         Jędrzejewski-Szmek
 
-        -- Berlin, 2014-06-11
+         Berlin, 2014-06-11
 
 CHANGES WITH 213:
 
@@ -2739,7 +3219,7 @@ CHANGES WITH 213:
         Lindskog, WaLyong Cho, Will Woods, Zbigniew
         Jędrzejewski-Szmek
 
-        -- Beijing, 2014-05-28
+         Beijing, 2014-05-28
 
 CHANGES WITH 212:
 
@@ -2888,7 +3368,7 @@ CHANGES WITH 212:
         Umut Tezduyar Lindskog, Wieland Hoffmann, Zbigniew
         Jędrzejewski-Szmek
 
-        -- Berlin, 2014-03-25
+         Berlin, 2014-03-25
 
 CHANGES WITH 211:
 
@@ -3012,7 +3492,7 @@ CHANGES WITH 211:
         Gundersen, Umut Tezduyar Lindskog, Uoti Urpala, Zachary Cook,
         Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2014-03-12
+         Berlin, 2014-03-12
 
 CHANGES WITH 210:
 
@@ -3117,7 +3597,7 @@ CHANGES WITH 210:
         Paaboel Andersen, Tom Gundersen, Umut Tezduyar Lindskog,
         Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2014-02-24
+         Berlin, 2014-02-24
 
 CHANGES WITH 209:
 
@@ -3573,7 +4053,7 @@ CHANGES WITH 209:
         Pavlín, Vincent Batts, WaLyong Cho, William Giokas, Yang
         Zhiyong, Yin Kangkai, Yuxuan Shui, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2014-02-20
+         Berlin, 2014-02-20
 
 CHANGES WITH 208:
 
@@ -3660,7 +4140,7 @@ CHANGES WITH 208:
         Michael Scherer, Michał Górny, Mike Gilbert, Patrick McCarty,
         Sebastian Ott, Tom Gundersen, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2013-10-02
+         Berlin, 2013-10-02
 
 CHANGES WITH 207:
 
@@ -3760,7 +4240,7 @@ CHANGES WITH 207:
         Paaboel Andersen, Tom Gundersen, Umut Tezduyar, WANG Chao,
         William Giokas, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2013-09-13
+         Berlin, 2013-09-13
 
 CHANGES WITH 206:
 
@@ -3859,14 +4339,14 @@ CHANGES WITH 206:
         Thomas H.P. Andersen, Tom Gundersen, Tomasz Torcz, William
         Giokas, Zbigniew Jędrzejewski-Szmek
 
-        -- Berlin, 2013-07-23
+         Berlin, 2013-07-23
 
 CHANGES WITH 205:
 
         * Two new unit types have been introduced:
 
           Scope units are very similar to service units, however, are
-          created out of pre-existing processes -- instead of PID 1
+          created out of pre-existing processes  instead of PID 1
           forking off the processes. By using scope units it is
           possible for system services and applications to group their
           own child processes (worker processes) in a powerful way
@@ -4972,7 +5452,7 @@ CHANGES WITH 192:
         * We do not mount the "cpuset" controller anymore together with
           "cpu" and "cpuacct", as "cpuset" groups generally cannot be
           started if no parameters are assigned to it. "cpuset" hence
-          broke code that assumed it it could create "cpu" groups and
+          broke code that assumed it could create "cpu" groups and
           just start them.
 
         * journalctl -f will now subscribe to terminal size changes,
diff --git a/README b/README
index 3d323cfb68267f8c9476b33da7e2c9ae832d6106..0cd868ade28b70e40163bbb3ddfca44f0e536b8c 100644 (file)
--- a/README
+++ b/README
@@ -116,6 +116,32 @@ flag.
 
 The PAM module is called pam_elogind.so, not pam_systemd.so.
 
+Elogind and the running cgroup controller
+-----------------------------------------
+While 'configure' runs, it will detect which controller is in place.
+If no controller is in place, configure will determine, that elogind
+should be its own controller, which will be a very limited one.
+
+This approach should generally work, but if you just have no cgroup
+controller in place, yet, or if you are currently switching to
+another one, this approach will fail.
+
+In this case you can do one of the two following things:
+
+ 1) Boot your system with the target init system and cgroup
+    controller, before configuring and building elogind, or
+ 2) Use the --with-cgroup-controller=name option.
+
+Example: If you plan to use openrc, but openrc has not yet booted
+         the machine, you can use
+         --with-cgroup-controller=openrc
+         to let elogind know that openrc will be the controller
+         in charge.
+
+However, if you set the controller at configure time to something
+different than what is in place, elogind will not start until that
+controller is actively used as the primary controller.
+
 License
 -------
 
diff --git a/TODO b/TODO
index 7437938bf0e12bba82fe9c2f62c0cf3c001a56d0..ef25ef578e667e7ad72c2ec39d6dec6e7eddf3fa 100644 (file)
--- a/TODO
+++ b/TODO
@@ -33,15 +33,68 @@ Janitorial Clean-ups:
 
 Features:
 
+* ProtectKernelLogs= (drops CAP_SYSLOG, add seccomp for syslog() syscall, and DeviceAllow to /dev/kmsg) in service files
+
+* ProtectClock= (drops CAP_SYS_TIMES, adds seecomp filters for settimeofday, adjtimex), sets DeviceAllow o /dev/rtc
+
+* ProtectMount= (drop mount/umount/pivot_root from seccomp, disallow fuse via DeviceAllow, imply Mountflags=slave)
+
+* ProtectDevices= should also take iopl/ioperm/pciaccess away
+
+* ProtectKeyRing= to take keyring calls away
+
+* PrivateUsers= which maps the all user ids except root and the one specified
+  in User= to nobody
+
+* Add AllocateUser= for allowing dynamic user ids per-service
+
+* Add DataDirectory=, CacheDirectory= and LogDirectory= to match
+  RuntimeDirectory=, and create it as necessary when starting a service, owned by the right user.
+
+* Add BindDirectory= for allowing arbitrary, private bind mounts for services
+
+* Beef up RootDirectory= to use namespacing/bind mounts as soon as fs
+  namespaces are enabled by the service
+
+* Add RootImage= for mounting a disk image or file as root directory
+
+* RestrictNamespaces= or so in services (taking away the ability to create namespaces, with setns, unshare, clone)
+
+* nspawn: make /proc/sys/net writable?
+
+* make sure the ratelimit object can deal with USEC_INFINITY as way to turn off things
+
+* journalctl: make sure -f ends when the container indicated by -M terminates
+
+* expose the "privileged" flag of ExecCommand on the bus, and open it up to
+  transient units
+
+* allow attaching additional journald log fields to cgroups
+
+* rework fopen_temporary() to make use of open_tmpfile_linkable() (problem: the
+  kernel doesn't support linkat() that replaces existing files, currently)
+
+* check if DeviceAllow= should split first, resolve specifiers later
+
+* transient units: don't bother with actually setting unit properties, we
+  reload the unit file anyway
+
+* journald: sigbus API via a signal-handler safe function that people may call
+  from the SIGBUS handler
+
+* when using UTF8, ellipsize with "…" rather than "...", so that we can show more contents before truncating
+
+* move specifier expansion from service_spawn() into load-fragment.c
+
+* optionally, also require WATCHDOG=1 notifications during service start-up and shutdown
+
+* resolved: when routing queries, make sure only look for the *longest* suffix...
+
 * delay activation of logind until somebody logs in, or when /dev/tty0 pulls it
   in or lingering is on (so that containers don't bother with it until PAM is used). also exit-on-idle
 
 * cache sd_event_now() result from before the first iteration...
 
-* remove Capabilities=, after all AmbientCapabilities= and CapabilityBoundingSet= should be enough.
-
-* support for the new copy_file_range() syscall
-
 * add systemctl stop --job-mode=triggering that follows TRIGGERED_BY deps and adds them to the same transaction
 
 * Maybe add a way how users can "pin" units into memory, so that they are not subject to automatic GC?
@@ -49,11 +102,9 @@ Features:
 * PID1: find a way how we can reload unit file configuration for
   specific units only, without reloading the whole of systemd
 
-* add an explicit parser for LimitNICE= and LimitRTPRIO= that verifies
+* add an explicit parser for LimitRTPRIO= that verifies
   the specified range and generates sane error messages for incorrect
-  specifications. Also, for LimitNICE= maybe introduce a syntax such
-  as "+5" or "-7" in order to make the limits more readable as they
-  are otherwise shifted by 20.
+  specifications.
 
 * do something about "/control" subcgroups in the unified cgroup hierarchy
 
@@ -61,12 +112,6 @@ Features:
 
 * push CPUAffinity= also into the "cpuset" cgroup controller (only after the cpuset controller got ported to the unified hierarchy)
 
-* add a new command "systemctl revert" or so, that removes all dropin
-  snippets in /run and /etc, and all unit files with counterparts in
-  /usr, and thus undoes what "systemctl set-property" and "systemctl
-  edit" create. Maybe even add "systemctl revert -a" to do this for
-  all units.
-
 * PID 1 should send out sd_notify("WATCHDOG=1") messages (for usage in the --user mode, and when run via nspawn)
 
 * consider throwing a warning if a service declares it wants to be "Before=" a .device unit.
@@ -78,17 +123,12 @@ Features:
 
 * man: document that unless you use StandardError=null the shell >/dev/stderr won't work in shell scripts in services
 
-* install: include generator dirs in unit file search paths
-
-* rework C11 utf8.[ch] to use char32_t instead of uint32_t when referring
-  to unicode chars, to make things more expressive.
-
 * fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline
 
 * docs: bring http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date
 
 * mounting and unmounting mount points manually with different source
-  devices will result in collected collected on all devices used.
+  devices will result in collected on all devices used.
   http://lists.freedesktop.org/archives/systemd-devel/2015-April/030225.html
 
 * add a job mode that will fail if a transaction would mean stopping
@@ -112,7 +152,8 @@ Features:
 
 * implement a per-service firewall based on net_cls
 
-* Port various tools to make use of verbs.[ch], where applicable
+* Port various tools to make use of verbs.[ch], where applicable: busctl,
+  bootctl, coredumpctl, hostnamectl, localectl, systemd-analyze, timedatectl
 
 * hostnamectl: show root image uuid
 
@@ -132,8 +173,6 @@ Features:
 * as soon as we have kdbus, and sender timestamps, revisit coalescing multiple parallel daemon reloads:
   http://lists.freedesktop.org/archives/systemd-devel/2014-December/025862.html
 
-* the install state probably shouldn't get confused by generated units, think dbus1/kdbus compat!
-
 * in systemctl list-unit-files: show the install value the presets would suggest for a service in a third column
 
 * figure out when we can use the coarse timers
@@ -145,8 +184,6 @@ Features:
 
 * firstboot: make it useful to be run immediately after yum --installroot to set up a machine. (most specifically, make --copy-root-password work even if /etc/passwd already exists
 
-* add infrastructure to allocate dynamic/transient users and UID ranges, for use in user-namespaced containers, per-seat gdm login screens and gdm guest sessions
-
 * maybe add support for specifier expansion in user.conf, specifically DefaultEnvironment=
 
 * introduce systemd-timesync-wait.service or so to sync on an NTP fix?
@@ -166,9 +203,7 @@ Features:
 
 * systemctl: if some operation fails, show log output?
 
-* systemctl edit:
-- allow creation of units from scratch
-- use equvalent of cat() to insert existing config as a comment, prepended with #.
+* systemctl edit: use equvalent of cat() to insert existing config as a comment, prepended with #.
   Upon editor exit, lines with one # are removed, lines with two # are left with one #, etc.
 
 * exponential backoff in timesyncd when we cannot reach a server
@@ -196,8 +231,8 @@ Features:
   - resolved should optionally register additional per-interface LLMNR
     names, so that for the container case we can establish the same name
     (maybe "host") for referencing the server, everywhere.
-  - enable DNSSEC by default
   - allow clients to request DNSSEC for a single lookup even if DNSSEC is off (?)
+  - hook up resolved with machined-based address resolution
 
 * refcounting in sd-resolve is borked
 
@@ -233,7 +268,7 @@ Features:
   CAP_NET_ADMIN is set, more than the loopback device is defined, even
   when it is otherwise off
 
-* MessageQueueMessageSize= and RLimitFSIZE= (and suchlike) should use parse_iec_size().
+* MessageQueueMessageSize= (and suchlike) should use parse_iec_size().
 
 * "busctl status" works only as root on dbus1, since we cannot read
   /proc/$PID/exe
@@ -248,7 +283,7 @@ Features:
   and passes this back to PID1 via SCM_RIGHTS. This also could be used
   to allow Chown/chgrp on sockets without requiring NSS in PID 1.
 
-* New service property: maximum CPU and wallclock runtime for a service
+* New service property: maximum CPU runtime for a service
 
 * introduce bus call FreezeUnit(s, b), as well as "systemctl freeze
   $UNIT" and "systemctl thaw $UNIT" as wrappers around this. The calls
@@ -278,8 +313,6 @@ Features:
 
 * be more careful what we export on the bus as (usec_t) 0 and (usec_t) -1
 
-* unify dispatch table in systemctl_main() and friends
-
 * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it
 
 * After coming back from hibernation reset hibernation swap partition using the /dev/snapshot ioctl APIs
@@ -321,10 +354,6 @@ Features:
        - path escaping
   - update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now
   - test bloom filter generation indexes
-  - bus-proxy: when passing messages from kdbus, make sure we properly
-    handle the case where a large number of fds is appended that we
-    cannot pass into sendmsg() of the AF_UNIX sokcet (which only accepts
-    253 messages)
   - kdbus: introduce a concept of "send-only" connections
   - kdbus: add counter for refused unicast messages that is passed out via the RECV ioctl. SImilar to the counter for dropped multicast messages we already have.
 
@@ -374,7 +403,7 @@ Features:
 
 * systemd-inhibit: make taking delay locks useful: support sending SIGINT or SIGTERM on PrepareForSleep()
 
-* remove any syslog support from log.c -- we probably cannot do this before split-off udev is gone for good
+* remove any syslog support from log.c  we probably cannot do this before split-off udev is gone for good
 
 * shutdown logging: store to EFI var, and store to USB stick?
 
@@ -494,8 +523,6 @@ Features:
     written to as FAIL, but instead show that their are being written to.
   - add journalctl -H that talks via ssh to a remote peer and passes through
     binary logs data
-  - change journalctl -M to acquire fd to journal directory via machined, and
-    then operate on that via openat() instead of absolute paths
   - add a version of --merge which also merges /var/log/journal/remote
   - log accumulated resource usage after each service invocation
   - journalctl: -m should access container journals directly by enumerating
@@ -529,19 +556,17 @@ Features:
   - systemctl enable: fail if target to alias into does not exist? maybe show how many units are enabled afterwards?
   - systemctl: "Journal has been rotated since unit was started." message is misleading
   - better error message if you run systemctl without systemd running
-  - systemctl status output should should include list of triggering units and their status
+  - systemctl status output should include list of triggering units and their status
 
 * unit install:
   - "systemctl mask" should find all names by which a unit is accessible
     (i.e. by scanning for symlinks to it) and link them all to /dev/null
-  - systemctl list-unit-files should list generated files (and probably with a new state "generated" for them, or so)
 
 * timer units:
   - timer units should get the ability to trigger when:
     o CLOCK_REALTIME makes jumps (TFD_TIMER_CANCEL_ON_SET)
     o DST changes
   - Support 2012-02~4 as syntax for specifying the fourth to last day of the month.
-  - calendarspec: support value ranges with ".." notation. Example: 2013-4..8-1
   - Modulate timer frequency based on battery state
 
 * add libsystemd-password or so to query passwords during boot using the password agent logic
@@ -561,8 +586,6 @@ Features:
   - to allow "linking" of nspawn containers, extend --network-bridge= so
     that it can dynamically create bridge interfaces that are refcounted
     by the containers on them. For each group of containers to link together
-  - refuses to boot containers without /etc/machine-id (OK?), and with empty
-    /etc/machine-id (not OK).
   - nspawn -x should support ephemeral instances of gpt images
   - emulate /dev/kmsg using CUSE and turn off the syslog syscall
     with seccomp. That should provide us with a useful log buffer that
@@ -583,8 +606,6 @@ Features:
   - should send out sd_notify("WATCHDOG=1") messages
   - optionally automatically add FORWARD rules to iptables whenever nspawn is
     running, remove them when shut down.
-  - add a logic for cleaning up read-only, hidden container images in
-    /var/lib/machines that are not ancestors of any non-hidden containers
   - Improve error message when --bind= is used on a non-existing source
     directory
   - maybe make copying of /etc/resolv.conf optional, and skip it if --read-only
@@ -628,8 +649,6 @@ Features:
 
 * initialize the hostname from the fs label of /, if /etc/hostname does not exist?
 
-* rename "userspace" to "core-os"
-
 * udev:
   - move to LGPL
   - kill scsi_id
@@ -744,17 +763,6 @@ Features:
   - Allow multiple ExecStart= for all Type= settings, so that we can cover rescue.service nicely
   - consider adding RuntimeDirectoryUser= + RuntimeDirectoryGroup=
 
-* systemd-python:
-   - figure out a simple way to wait for journal events in a way that
-     works with ^C
-   - add documentation to systemd.daemon
-
-* bootchart:
-   - plot per-process IO utilization
-   - group processes based on service association (cgroups)
-   - document initcall_debug
-   - kernel cmdline "bootchart" option for simplicity?
-
 * udev-link-config:
    - Make sure ID_PATH is always exported and complete for
      network devices where possible, so we can safely rely
@@ -776,7 +784,6 @@ Features:
    - work with non-Ethernet devices
    - add support for more bond options
    - dhcp: do we allow configuring dhcp routes on interfaces that are not the one we got the dhcp info from?
-   - add LLDP client side support
    - the DHCP lease data (such as NTP/DNS) is still made available when
      a carrier is lost on a link. It should be removed instantly.
    - expose in the API the following bits:
index c4d879a64421f13f770b41aba1c41eed45c2424f..8524706f5e180aa03607e9e29460187a0de370b8 100644 (file)
                </Unit>
                <Unit filename="../src/basic/mempool.h" />
                <Unit filename="../src/basic/missing.h" />
+               <Unit filename="../src/basic/missing_syscall.h" />
                <Unit filename="../src/basic/mkdir-label.c">
                        <Option compilerVar="CC" />
                </Unit>
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/basic/mount-util.h" />
-               <Unit filename="../src/basic/musl_missing.c">
-                       <Option compilerVar="CC" />
-               </Unit>
-               <Unit filename="../src/basic/musl_missing.h" />
                <Unit filename="../src/basic/parse-printf-format.c">
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/libelogind/sd-login/test-login.c">
                        <Option compilerVar="CC" />
                </Unit>
+               <Unit filename="../src/login/eloginctl.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/login/eloginctl.h" />
+               <Unit filename="../src/login/elogind-action.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/login/elogind-action.h" />
+               <Unit filename="../src/login/elogind-dbus.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/login/elogind-dbus.h" />
+               <Unit filename="../src/login/elogind.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/login/elogind.h" />
                <Unit filename="../src/login/inhibit.c">
                        <Option compilerVar="CC" />
                </Unit>
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/login/logind-device.h" />
+               <Unit filename="../src/login/logind-gperf.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/login/logind-gperf.gperf" />
                <Unit filename="../src/login/logind-inhibit.c">
                        <Option compilerVar="CC" />
                </Unit>
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/login/logind-session.h" />
-               <Unit filename="../src/login/logind-sleep.c">
-                       <Option compilerVar="CC" />
-               </Unit>
-               <Unit filename="../src/login/logind-sleep.h" />
                <Unit filename="../src/login/logind-user-dbus.c">
                        <Option compilerVar="CC" />
                </Unit>
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/login/logind-user.h" />
+               <Unit filename="../src/login/logind-utmp.c">
+                       <Option compilerVar="CC" />
+               </Unit>
                <Unit filename="../src/login/logind.c">
                        <Option compilerVar="CC" />
                </Unit>
-               <Unit filename="../src/login/logind.conf" />
+               <Unit filename="../src/login/logind.conf.in" />
                <Unit filename="../src/login/logind.h" />
                <Unit filename="../src/login/pam_elogind.c">
                        <Option compilerVar="CC" />
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/shared/conf-parser.h" />
+               <Unit filename="../src/shared/musl_missing.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/shared/musl_missing.h" />
                <Unit filename="../src/shared/pager.c">
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/shared/pager.h" />
-               <Unit filename="../src/shared/path-lookup.h" />
+               <Unit filename="../src/shared/sleep-config.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/shared/sleep-config.h" />
                <Unit filename="../src/shared/spawn-polkit-agent.c">
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/shared/spawn-polkit-agent.h" />
                <Unit filename="../src/shared/test-tables.h" />
                <Unit filename="../src/shared/udev-util.h" />
+               <Unit filename="../src/shared/utmp-wtmp.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/shared/utmp-wtmp.h" />
+               <Unit filename="../src/sleep/sleep.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/sleep/sleep.h" />
                <Unit filename="../src/systemd/_sd-common.h" />
                <Unit filename="../src/systemd/sd-bus-protocol.h" />
                <Unit filename="../src/systemd/sd-bus-vtable.h" />
                <Unit filename="../src/systemd/sd-id128.h" />
                <Unit filename="../src/systemd/sd-login.h" />
                <Unit filename="../src/systemd/sd-messages.h" />
+               <Unit filename="../src/update-utmp/update-utmp.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/update-utmp/update-utmp.h" />
                <Extensions>
                        <envvars />
                        <code_completion />
diff --git a/coccinelle/xsprintf.cocci b/coccinelle/xsprintf.cocci
deleted file mode 100644 (file)
index 401216a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-@@
-expression e, fmt;
-expression list vaargs;
-@@
-- snprintf(e, sizeof(e), fmt, vaargs);
-+ xsprintf(e, fmt, vaargs);
index 16cb509067e55cea727c2105ebac4d7512f3b920..f1efe2164416e5be385b31bbb92cb72af56670ad 100644 (file)
@@ -20,7 +20,7 @@
 AC_PREREQ([2.64])
 
 AC_INIT([elogind],
-        [229.1],
+        [231.3],
         [https://github.com/elogind/elogind/issues],
         [elogind],
         [https://github.com/elogind/elogind])
@@ -111,20 +111,52 @@ fi
 
 
 # ------------------------------------------------------------------------------
-# Find running cgroup controller
+# Let users set the cgroup controller to use, in case the target controller
+# isn't currently running the show.
+# Example: Gentoo Linux, user wants to switch from systemd to openrc+elogind,
+#          and emerges elogind before having booted the machine with openrc.
+#          See: https://github.com/elogind/elogind/issues/18
 with_cgroupctrl=
-AS_IF(  [test -f /proc/self/cgroup], [
-        # If the init system is a cgroup controler, it will be position 1.
-        # Secondary controllers, like cgmanager, do not work.
-        with_cgroupctrl=`grep "^1:name=" /proc/self/cgroup | cut -d ':' -f 2`
-        AS_IF(  [test -z "$with_cgroupctrl"], [
-                # Try to be our own cgroup controller
-                with_cgroupctrl="name=elogind"
+AC_ARG_WITH([cgroup-controller],
+            AS_HELP_STRING([--with-cgroup-controller=name],
+            [Set the name of the cgroup controller to use.
+             Use this when the autodetection fails, or you plan to use your system with a different controller than the one in place now.
+             The value 'auto' (default) detects the running controller.
+             The values 'none' and 'elogind' will cause elogind to be its own (very limited) controller.
+             When elogind shall be its own controller, there *MUST NOT* be any other controller running!
+             Another popular controller would be 'openrc'.]),
+            [with_cgroupctrl=$withval],
+            [with_cgroupctrl=auto])
+
+# ------------------------------------------------------------------------------
+# Find running cgroup controller, if none was set
+AS_IF(  [test "x$with_cgroupctrl" = "xauto"], [
+        AS_IF([test -f /proc/self/cgroup], [
+                # If the init system is a cgroup controler, it will be position 1.
+                # Secondary controllers, like cgmanager, do not work.
+                with_cgroupctrl=`grep "^1:name=" /proc/self/cgroup | \
+                        sed -n 's/.*=//p' | sed -e 's/:.*$//'`
+                AS_IF(  [test -z "$with_cgroupctrl"], [
+                        # Try to be our own cgroup controller
+                        with_cgroupctrl="elogind"
+                        ])
+        ], [
+                # 'auto' but no cgroup fs is a problem.
+                with_cgroupctrl=""
         ])
 ])
-AS_IF(  [test -z "$with_cgroupctrl"],
-        AC_MSG_ERROR([No running cgroup controller found]))
 
+# If the user specified 'none', switch to 'elogind'.
+# 'none' is allowed, as this means "there is no controller now"
+AS_IF(  [test "x$with_cgroupctrl" = "xnone"], [with_cgroupctrl=elogind])
+
+# If this was not possible, /proc/self/cgroup not mounted yet, and 'auto'
+# chosen, error out.
+AS_IF(  [test -z "$with_cgroupctrl"],
+        AC_MSG_ERROR([No running cgroup controller found]), [
+        # Otherwise add the 'name=' prefix
+        with_cgroupctrl="name=$with_cgroupctrl"
+])
 
 # ------------------------------------------------------------------------------
 address_sanitizer_cflags=
@@ -267,6 +299,7 @@ AC_CHECK_SIZEOF(uid_t)
 AC_CHECK_SIZEOF(gid_t)
 AC_CHECK_SIZEOF(time_t)
 AC_CHECK_SIZEOF(dev_t)
+AC_CHECK_SIZEOF(ino_t)
 AC_CHECK_SIZEOF(rlim_t,,[
        #include <sys/time.h>
        #include <sys/resource.h>
@@ -343,11 +376,20 @@ AC_SEARCH_LIBS([cap_init], [cap], [], [AC_MSG_ERROR([*** POSIX caps library not
 CAP_LIBS="$LIBS"
 AC_SUBST(CAP_LIBS)
 
-AC_CHECK_FUNCS([memfd_create])
 AC_CHECK_FUNCS([__secure_getenv secure_getenv])
-AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, getrandom, renameat2,
-                char16_t, char32_t, LO_FLAGS_PARTSCAN],
-               [], [], [[
+AC_CHECK_DECLS([
+        memfd_create,
+        gettid,
+        pivot_root,
+        name_to_handle_at,
+        setns,
+        getrandom,
+        renameat2,
+        kcmp,
+        keyctl,
+        LO_FLAGS_PARTSCAN,
+        copy_file_range],
+                [], [], [[
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/mount.h>
@@ -357,7 +399,14 @@ AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, getrandom, renamea
 #include <linux/random.h>
 ]])
 
+AC_CHECK_TYPES([char16_t, char32_t, key_serial_t],
+               [], [], [[
+#include <uchar.h>
+]])
+
 AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
+                IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
+                IFLA_VRF_TABLE,
                 IFLA_MACVLAN_FLAGS,
                 IFLA_IPVLAN_MODE,
                 IFLA_VTI_REMOTE,
@@ -368,8 +417,9 @@ AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
                 IFLA_IPTUN_ENCAP_DPORT,
                 IFLA_GRE_ENCAP_DPORT,
                 IFLA_BRIDGE_VLAN_INFO,
+                IFLA_BRPORT_PROXYARP,
                 IFLA_BRPORT_LEARNING_SYNC,
-                IFLA_BR_PRIORITY,
+                IFLA_BR_VLAN_DEFAULT_PVID,
                 NDA_IFINDEX,
                 IFA_FLAGS],
 [], [], [[
@@ -405,6 +455,16 @@ AC_ARG_WITH([udevbindir],
             [with_udevbindir=$($PKG_CONFIG --variable=udevdir udev)])
 AC_SUBST([udevbindir], [$with_udevbindir])
 
+# ------------------------------------------------------------------------------
+have_utmp=yes
+AC_ARG_ENABLE([utmp], AS_HELP_STRING([--disable-utmp], [disable utmp/wtmp log handling]),
+        AS_CASE("x${enableval}",
+                [xyes], [have_utmp=yes],
+                [xno],  [have_utmp=no],
+                AC_MSG_ERROR(bad value ${enableval} for --enable-utmp)))
+AS_IF([test "x$have_utmp" = "xyes"], [AC_DEFINE(HAVE_UTMP, 1, [Define if utmp/wtmp support is enabled])])
+AM_CONDITIONAL([HAVE_UTMP], [test "x$have_utmp" = "xyes"])
+
 # ------------------------------------------------------------------------------
 have_coverage=no
 AC_ARG_ENABLE(coverage, AS_HELP_STRING([--enable-coverage], [enable test coverage]))
@@ -443,6 +503,17 @@ if test "x$enable_selinux" != "xno"; then
 fi
 AM_CONDITIONAL(HAVE_SELINUX, [test "$have_selinux" = "yes"])
 
+# ------------------------------------------------------------------------------
+AC_ARG_WITH([kill-user-processes],
+        [AS_HELP_STRING([--without-kill-user-processes], [Set elogind's KillUserProcesses=no by default])])
+AS_IF([test "$with_kill_user_processes" != "no"],
+       [kill_user_processes=true
+        KILL_USER_PROCESSES=yes],
+       [kill_user_processes=false
+        KILL_USER_PROCESSES=no])
+AC_DEFINE_UNQUOTED(KILL_USER_PROCESSES, [$kill_user_processes], [Default KillUserProcesses setting])
+AC_SUBST(KILL_USER_PROCESSES)
+
 # ------------------------------------------------------------------------------
 AC_ARG_ENABLE([pam],
         AS_HELP_STRING([--disable-pam],[Disable optional PAM support]),
@@ -584,16 +655,6 @@ if test "x$enable_polkit" != "xno"; then
 fi
 AM_CONDITIONAL(ENABLE_POLKIT, [test "x$have_polkit" = "xyes"])
 
-# ------------------------------------------------------------------------------
-have_kdbus=no
-AC_ARG_ENABLE(kdbus, AS_HELP_STRING([--disable-kdbus], [do not connect to kdbus by default]))
-if test "x$enable_kdbus" != "xno"; then
-        AC_DEFINE(ENABLE_KDBUS, 1, [Define if kdbus is to be connected to by default])
-        have_kdbus=yes
-        M4_DEFINES="$M4_DEFINES -DENABLE_KDBUS"
-fi
-AM_CONDITIONAL(ENABLE_KDBUS, [test "$have_kdbus" = "yes"])
-
 # ------------------------------------------------------------------------------
 AC_CHECK_HEADERS_ONCE([valgrind/memcheck.h valgrind/valgrind.h])
 
@@ -750,12 +811,13 @@ AC_MSG_RESULT([
         SELinux:                 ${have_selinux}
         SMACK:                   ${have_smack}
         ACL:                     ${have_acl}
+        KillUserProcesses default: ${KILL_USER_PROCESSES}
         polkit:                  ${have_polkit}
-        kdbus:                   ${have_kdbus}
         Python:                  ${have_python}
         man pages:               ${have_manpages}
         test coverage:           ${have_coverage}
         Split /usr:              ${enable_split_usr}
+        utmp/wtmp support:       ${have_utmp}
         Link time optimization:  ${have_lto}
         extra debugging:         ${enable_debug}
         cgroup controller:       ${with_cgroupctrl}
index 545f4b306e3163ecbe4f1655d849bda8f2a28d4f..f1271dcb1fc46db807e163857d510af6f53f4923 100644 (file)
 
 <!--
   - helper template to do conflict resolution between various headings with the same inferred ID attribute/tag from the headerlink template
-  - this conflict resolution is necessary to prevent malformed HTML output (multiple id attributes with the same value)
+  - this conflict resolution is necessary to prevent malformed HTML output (multiple ID attributes with the same value)
   - and it fixes xsltproc warnings during compilation of HTML man pages
   -
   - A simple top-to-bottom numbering scheme is implemented for nodes with the same ID value to derive unique ID values for HTML output.
   <!--
     - If stable URLs with fragment markers (references to the ID) turn out not to be important:
     - generatedID could simply take the value of generate-id(), and various other helper templates may be dropped entirely.
-    - Alternatively if xsltproc is patched to generate reproducible generate-id() output the same simplifications can be
+    - Alternatively, if xsltproc is patched to generate reproducible generate-id() output, the same simplifications can be
     - applied at the cost of breaking compatibility with URLs generated from output of previous versions of this stylesheet.
    -->
   <xsl:variable name="generatedID">
index 08a37cd54adef3ea23e017ed663a90328fc61953..140249fc2241ea7e7fcc2a4dbc336c41425309ca 100644 (file)
@@ -21,7 +21,8 @@
   along with elogind; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="elogind">
+<refentry id="elogind"
+    xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>elogind</title>
index f0f5419ca7e2d5137c0be7017be8692ad7cc7d10..0f638c260c4eaeb0cbe4be5366f1f56b584485ce 100644 (file)
@@ -21,7 +21,8 @@
   along with elogind; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="loginctl" xmlns:xi="http://www.w3.org/2001/XInclude">
+<refentry id="loginctl"
+    xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>loginctl</title>
         shown.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--value</option></term>
+
+        <listitem>
+          <para>When printing properties with <command>show</command>,
+          only print the value, and skip the property name and
+          <literal>=</literal>.</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>-a</option></term>
         <term><option>--all</option></term>
         <term><command>activate</command> <optional><replaceable>ID</replaceable></optional></term>
 
         <listitem><para>Activate a session. This brings a session into
-        the foreground, if another session is currently in the
+        the foreground if another session is currently in the
         foreground on the respective seat. Takes a session identifier
-        as argument. If no argument is specified the session of the
+        as argument. If no argument is specified, the session of the
         caller is put into foreground.</para></listitem>
       </varlistentry>
 
         <listitem><para>Activates/deactivates the screen lock on one
         or more sessions, if the session supports it. Takes one or
         more session identifiers as arguments. If no argument is
-        specified the session of the caller is locked/unlocked.
+        specified, the session of the caller is locked/unlocked.
         </para></listitem>
       </varlistentry>
 
         spawned for the user at boot and kept around after logouts.
         This allows users who are not logged in to run long-running
         services. Takes one or more user names or numeric UIDs as
-        argument. If no argument is specified enables/disables
-        lingering for the user of the session of the caller.
+        argument. If no argument is specified, enables/disables
+        lingering for the user of the session of the caller.</para>
+
+        <para>See also <varname>KillUserProcesses=</varname> setting in
+        <citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
         </para></listitem>
       </varlistentry>
 
         seat. The devices should be specified via device paths in the
         <filename>/sys</filename> file system. To create a new seat,
         attach at least one graphics card to a previously unused seat
-        name. Seat names may consist only of a-z, A-Z, 0-9,
+        name. Seat names may consist only of a–z, A–Z, 0–9,
         <literal>-</literal> and <literal>_</literal> and must be
         prefixed with <literal>seat</literal>. To drop assignment of a
         device to a specific seat, just reassign it to a different
     otherwise.</para>
   </refsect1>
 
+  <refsect1>
+    <title>Examples</title>
+
+    <example>
+      <title>Querying user status</title>
+
+      <programlisting>$ loginctl user-status
+fatima (1005)
+           Since: Sat 2016-04-09 14:23:31 EDT; 54min ago
+           State: active
+        Sessions: 5 *3
+            Unit: user-1005.slice
+                  ├─user@1005.service
+                    ...
+                  ├─session-3.scope
+                    ...
+                  └─session-5.scope
+                    ├─3473 login -- fatima
+                    └─3515 -zsh
+
+Apr 09 14:40:30 laptop login[2325]: pam_unix(login:session):
+                       session opened for user fatima by LOGIN(uid=0)
+Apr 09 14:40:30 laptop login[2325]: LOGIN ON tty3 BY fatima
+</programlisting>
+
+      <para>There are two sessions, 3 and 5. Session 3 is a graphical session,
+      marked with a star. The tree of processing including the two corresponding
+      scope units and the user manager unit are shown.</para>
+    </example>
+  </refsect1>
+
   <xi:include href="less-variables.xml" />
 
   <refsect1>
index 3a56c29627fbd8683a0cb506087a9e7102336268..4641bbb833cb2c82ee3e939e5252b38543c980c7 100644 (file)
           <term><varname>HandleLidSwitch=</varname></term>
           <term><varname>HandleLidSwitchDocked=</varname></term>
 
-          <listitem><para>Controls whether logind shall handle the
+          <listitem><para>Controls how logind shall handle the
           system power and sleep keys and the lid switch to trigger
           actions such as system power-off or suspend. Can be one of
           <literal>ignore</literal>,
           docking station, or if more than one display is connected, the
           action specified by <varname>HandleLidSwitchDocked=</varname>
           occurs; otherwise the <varname>HandleLidSwitch=</varname>
-          action occurs.</para></listitem>
-        </varlistentry>
+        action occurs.</para>
+
+        <para>A different application may disable logind's handling of system power and
+        sleep keys and the lid switch by taking a low-level inhibitor lock
+        ("handle-power-key", "handle-suspend-key", "handle-hibernate-key",
+        "handle-lid-switch"). This is most commonly used by graphical desktop environments
+        to take over suspend and hibernation handling, and to use their own configuration
+        mechanisms. If a low-level inhibitor lock is taken, logind will not take any
+        action when that key or switch is triggered and the <varname>Handle*=</varname>
+        settings are irrelevant.</para></listitem>
+      </varlistentry>
 
         <varlistentry>
           <term><varname>PowerKeyIgnoreInhibited=</varname></term>
           <term><varname>HibernateKeyIgnoreInhibited=</varname></term>
           <term><varname>LidSwitchIgnoreInhibited=</varname></term>
 
-          <listitem><para>Controls whether actions triggered by the
-          power and sleep keys and the lid switch are subject to
-          inhibitor locks. These settings take boolean arguments. If
-          <literal>no</literal>, the inhibitor locks taken by
-          applications in order to block the requested operation are
-          respected. If <literal>yes</literal>, the requested operation
-          is executed in any case.
+        <listitem><para>Controls whether actions that <command>systemd-logind</command>
+        takes when the power and sleep keys and the lid switch are triggered are subject
+        to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor
+        locks ("handle-*-key"), are always honoured, irrespective of this setting.</para>
+
+        <para>These settings take boolean arguments. If <literal>no</literal>, the
+        inhibitor locks taken by applications are respected. If <literal>yes</literal>,
+        "shutdown", "sleep", and "idle" inhibitor locks are ignored.
           <varname>PowerKeyIgnoreInhibited=</varname>,
-          <varname>SuspendKeyIgnoreInhibited=</varname> and
-          <varname>HibernateKeyIgnoreInhibited=</varname> default to
-          <literal>no</literal>.
-          <varname>LidSwitchIgnoreInhibited=</varname> defaults to
-          <literal>yes</literal>. This means that the lid switch does
-          not respect suspend blockers by default, but the power and
-          sleep keys do. </para></listitem>
+        <varname>SuspendKeyIgnoreInhibited=</varname>, and
+        <varname>HibernateKeyIgnoreInhibited=</varname> default to <literal>no</literal>.
+        <varname>LidSwitchIgnoreInhibited=</varname> defaults to <literal>yes</literal>.
+        This means that when <command>systemd-logind</command> is handling events by
+        itself (no low level inhibitor locks are taken by another application), the lid
+        switch does not respect suspend blockers by default, but the power and sleep keys
+        do.</para></listitem>
         </varlistentry>
 
         <varlistentry>
index 5c363f96b33d90276f9bc2e67d6aae574e5cb769..3ba7c3bd3e4eff6b3f990001fedfb740708909c5 100644 (file)
     returned in the <parameter>source</parameter> parameter. The
     <parameter>fd</parameter> parameter takes the UNIX file descriptor
     to watch, which may refer to a socket, a FIFO, a message queue, a
-    serial connection, a character device or any other file descriptor
-    compatible with Linux <citerefentry
-    project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>. The
-    <parameter>events</parameter> parameter takes a bit mask of I/O
-    events to watch the file descriptor for, a combination of the
-    following event flags: <constant>EPOLLIN</constant>,
-    <constant>EPOLLOUT</constant>, <constant>EPOLLRDHUP</constant>,
-    <constant>EPOLLPRI</constant> and <constant>EPOLLET</constant>,
-    see <citerefentry
-    project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    serial connection, a character device, or any other file descriptor
+    compatible with Linux
+    <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>. The
+    <parameter>events</parameter> parameter takes a bit mask of events
+    to watch for, a combination of the following event flags:
+    <constant>EPOLLIN</constant>, <constant>EPOLLOUT</constant>,
+    <constant>EPOLLRDHUP</constant>, <constant>EPOLLPRI</constant>,
+    and <constant>EPOLLET</constant>, see
+    <citerefentry project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     for details. The <parameter>handler</parameter> shall reference a
-    function to call when the I/O event source is triggered. The
-    handler function will be passed the
-    <parameter>userdata</parameter> pointer, which may be chosen
-    freely by the caller. The handler will also be passed the file
-    descriptor the event was seen on as well as the actual event flags
-    seen. It's generally a subset of the events watched, however may
-    additionally have <constant>EPOLLERR</constant> and
-    <constant>EPOLLHUP</constant> set.</para>
-
-    <para>By default, the I/O event source will stay enabled
+    function to call when the event source is triggered. The
+    <parameter>userdata</parameter> pointer will be passed to the
+    handler function, and may be chosen freely by the caller. The
+    handler will also be passed the file descriptor the event was seen
+    on, as well as the actual event flags. It's generally a subset of
+    the events watched, however may additionally include
+    <constant>EPOLLERR</constant> and <constant>EPOLLHUP</constant>.
+    </para>
+
+    <para>By default, an event source will stay enabled
     continuously (<constant>SD_EVENT_ON</constant>), but this may be
     changed with
     <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
     If the handler function returns a negative error code, it will be
     disabled after the invocation, even if the
     <constant>SD_EVENT_ON</constant> mode was requested before. Note
-    that an I/O event source set to <constant>SD_EVENT_ON</constant> will
-    fire continuously unless data is read or written to the file
-    descriptor in order to reset the mask of events seen.
+    that an event source set to <constant>SD_EVENT_ON</constant> will
+    fire continuously unless data is read from or written to the file
+    descriptor to reset the mask of events seen.
     </para>
 
     <para>Setting the I/O event mask to watch for to 0 does not mean
     <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     but note that the event source is only removed from the event loop
     when all references to the event source are dropped. To make sure
-    an event source does not fire anymore, even when there's still a
-    reference to it kept, consider setting the event source to
-    <constant>SD_EVENT_OFF</constant> with
-    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+    an event source does not fire anymore, even if it is still referenced,
+    disable the event source using
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    with <constant>SD_EVENT_OFF</constant>.</para>
 
     <para>If the second parameter of
-    <function>sd_event_add_io()</function> is passed as NULL no
-    reference to the event source object is returned. In this case the
-    event source is considered "floating", and will be destroyed
-    implicitly when the event loop itself is destroyed.</para>
+    <function>sd_event_add_io()</function> is
+    <constant>NULL</constant> no reference to the event source object
+    is returned. In this case the event source is considered
+    "floating", and will be destroyed implicitly when the event loop
+    itself is destroyed.</para>
 
     <para>It is recommended to use
     <function>sd_event_add_io()</function> only in conjunction with
     ensure that all I/O operations from invoked handlers are properly
     asynchronous and non-blocking. Using file descriptors without
     <constant>O_NONBLOCK</constant> might result in unexpected
-    starving of other event sources. See <citerefentry
-    project='man-pages'><refentrytitle>fcntl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    starvation of other event sources. See
+    <citerefentry project='man-pages'><refentrytitle>fcntl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     for details on enabling <constant>O_NONBLOCK</constant> mode.</para>
 
     <para><function>sd_event_source_get_io_events()</function> retrieves
-    the configured I/O event mask to watch of an I/O event source created
+    the configured mask of watched I/O events of an event source created
     previously with <function>sd_event_add_io()</function>. It takes
     the event source object and a pointer to a variable to store the
-    event mask in.</para>
+    mask in.</para>
 
-    <para><function>sd_event_source_set_io_events()</function> changes the
-    configured I/O event mask to watch of an I/O event source created previously
-    with <function>sd_event_add_io()</function>. It takes the event
-    source object and the new event mask to set.</para>
+    <para><function>sd_event_source_set_io_events()</function>
+    configures the mask of watched I/O events of an event source created
+    previously with <function>sd_event_add_io()</function>. It takes the
+    event source object and the new event mask.</para>
 
-    <para><function>sd_event_source_get_io_events()</function>
+    <para><function>sd_event_source_get_io_revents()</function>
     retrieves the I/O event mask of currently seen but undispatched
-    events from an I/O event source created previously with
+    events from an event source created previously with
     <function>sd_event_add_io()</function>. It takes the event source
     object and a pointer to a variable to store the event mask
     in. When called from a handler function on the handler's event
     source types, the latter only to I/O event sources.</para>
 
     <para><function>sd_event_source_get_io_fd()</function> retrieves
-    the UNIX file descriptor of an I/O event source created previously
+    the UNIX file descriptor of an event source created previously
     with <function>sd_event_add_io()</function>. It takes the event
-    source object and returns the positive file descriptor in the return
-    value, or a negative error number on error (see below).</para>
+    source object and returns the non-negative file descriptor
+    or a negative error number on error (see below).</para>
 
     <para><function>sd_event_source_set_io_fd()</function>
     changes the UNIX file descriptor of an I/O event source created
     previously with <function>sd_event_add_io()</function>. It takes
-    the event source object and the new file descriptor to set.</para>
+    the event source object and the new file descriptor.</para>
   </refsect1>
 
   <refsect1>
 
     <para>On success, these functions return 0 or a positive
     integer. On failure, they return a negative errno-style error
-    code. </para>
+    code.</para>
   </refsect1>
 
   <refsect1>
     <title>Errors</title>
 
-    <para>Returned errors may indicate the following problems:</para>
+    <para>Returned values may indicate the following problems:</para>
 
     <variablelist>
       <varlistentry>
index 219e261fd4a7031bca6fa870b3202f37bb8bf8e2..b419e7d8210aac15f21d6793ebe5177e90161c39 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <para><function>sd_event_now()</function> returns the timestamp
-    the most recent event loop iteration began. This timestamp is
-    taken right after returning from the event sleep, and before
+    <para><function>sd_event_now()</function> returns the time when
+    the most recent event loop iteration began. A timestamp
+    is taken right after returning from the event sleep, and before
     dispatching any event sources. The <parameter>event</parameter>
-    parameter takes the even loop object to retrieve the timestamp
+    parameter specifies the event loop object to retrieve the timestamp
     from. The <parameter>clock</parameter> parameter specifies the clock to
     retrieve the timestamp for, and is one of
-    <constant>CLOCK_REALTIME</constant> (or its equivalent
+    <constant>CLOCK_REALTIME</constant> (or equivalently
     <constant>CLOCK_REALTIME_ALARM</constant>),
-    <constant>CLOCK_MONOTONIC</constant> or
-    <constant>CLOCK_BOOTTIME</constant> (or its equivalent
-    <constant>CLOCK_BOOTTIME_ALARM</constant>), see <citerefentry
-    project='man-pages'><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    <constant>CLOCK_MONOTONIC</constant>, or
+    <constant>CLOCK_BOOTTIME</constant> (or equivalently
+    <constant>CLOCK_BOOTTIME_ALARM</constant>), see
+    <citerefentry project='man-pages'><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     for more information on the various clocks. The retrieved
     timestamp is stored in the <parameter>usec</parameter> parameter,
     in µs since the clock's epoch. If this function is invoked before
-    the first event loop iteration the current time is returned, as
+    the first event loop iteration, the current time is returned, as
     reported by <function>clock_gettime()</function>. To distinguish
     this case from a regular invocation the return value will be
-    positive non-zero in this case, while it is zero when the returned
-    timestamp refers to the actual event loop iteration.</para>
+    positive, and zero when the returned timestamp refers to an actual
+    event loop iteration.</para>
   </refsect1>
 
   <refsect1>
     <title>Return Value</title>
 
     <para>If the first event loop iteration has not run yet
-    <function>sd_event_now()</function> returns the requested
-    timestamp in <parameter>usec</parameter> and returns a positive,
-    non-zero return value. Otherwise, on success it will return the
-    iteration's timestamp in <parameter>usec</parameter> and 0 as
-    return value. On failure, the call returns a negative errno-style
+    <function>sd_event_now()</function> writes current time to
+    <parameter>usec</parameter> and returns a positive return value.
+    Otherwise, it will write the requested timestamp to <parameter>usec</parameter>
+    and return 0. On failure, the call returns a negative errno-style
     error code.</para>
   </refsect1>
 
   <refsect1>
     <title>Errors</title>
 
-    <para>Returned errors may indicate the following problems:</para>
+    <para>Returned values may indicate the following problems:</para>
 
     <variablelist>
       <varlistentry>
index 1339d50461d622c89804ca325d6ef01c8cf5d53d..ea3c21db86fb57f03041bba29b2d9afbea4ae8ad 100644 (file)
@@ -87,7 +87,7 @@
     <para>For I/O event sources, as created with
     <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     the call
-    <citerefentry><refentrytitle>sd_event_get_io_revents</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    <citerefentry><refentrytitle>sd_event_source_get_io_revents</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     may be used to query the type of event pending in more
     detail.</para>
 
index d1acd8e658c61686e37630abca8c422a70ec3377..6457cfc9b7e49bea658badbbbd932d22fdc917e7 100644 (file)
@@ -97,7 +97,7 @@
     <constant>SD_EVENT_PRIORITY_IDLE</constant> (100) may be used to
     indicate event sources that shall be dispatched early, normally or
     late. It is recommended to specify priorities based on these
-    definitions, and relative to them -- however, the full 64bit
+    definitions, and relative to them  however, the full 64bit
     signed integer range is available for ordering event
     sources.</para>
 
index a6c5e89479c95f37c7ce56f2a6fff26de67480a2..963213797075ec398f4df1b568deefd7a72bc477 100644 (file)
         <term><constant>-EINVAL</constant></term>
 
         <listitem><para>An input parameter was invalid (out of range,
-        or NULL, where that's not accepted).</para></listitem>
+        or NULL, where that is not accepted).</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 8f3efc145a80d0961179cd1eb6817dbf52b67e4a..11bee6919a7e53aeeca4e70c355184827b6335f9 100644 (file)
     lowercase hexadecimal digits and be terminated by a
     <constant>NUL</constant> byte.</para>
 
-    <para><function>sd_id128_from_string()</function> implements the
-    reverse operation: it takes a 33 character string with 32
-    hexadecimal digits (either lowercase or uppercase, terminated by
-    <constant>NUL</constant>) and parses them back into a 128-bit ID
-    returned in <parameter>ret</parameter>. Alternatively, this call
-    can also parse a 37-character string with a 128-bit ID formatted
-    as RFC UUID.</para>
+    <para><function>sd_id128_from_string()</function> implements the reverse operation: it takes a 33 character string
+    with 32 hexadecimal digits (either lowercase or uppercase, terminated by <constant>NUL</constant>) and parses them
+    back into a 128-bit ID returned in <parameter>ret</parameter>. Alternatively, this call can also parse a
+    37-character string with a 128-bit ID formatted as RFC UUID. If <parameter>ret</parameter> is passed as NULL the
+    function will validate the passed ID string, but not actually return it in parsed form.</para>
 
     <para>For more information about the <literal>sd_id128_t</literal>
     type see
index 4a3f513f6e0eaea29c4293302d5b57771f71808b..be872eac815d47287abb97ecd4c02dedb85b75b3 100644 (file)
         <term><constant>-EINVAL</constant></term>
 
         <listitem><para>An input parameter was invalid (out of range,
-        or NULL, where that's not accepted).</para></listitem>
+        or NULL, where that is not accepted).</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 2345aea4bf53ffed5141c8c84a128b61e0e908c2..03efe0193a7501bfd3bb4863feaa1903bc335156 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 
     <para><function>sd_notify()</function> may be called by a service
     to notify the service manager about state changes. It can be used
     to send arbitrary information, encoded in an
-    environment-block-like string. Most importantly it can be used for
+    environment-block-like string. Most importantly, it can be used for
     start-up completion notification.</para>
 
     <para>If the <parameter>unset_environment</parameter> parameter is
         to the service manager that describes the service state. This
         is free-form and can be used for various purposes: general
         state feedback, fsck-like programs could pass completion
-        percentages and failing programs could pass a human readable
+        percentages and failing programs could pass a human-readable
         error message. Example: <literal>STATUS=Completed 66% of file
         system check...</literal></para></listitem>
       </varlistentry>
         watchdog timestamp. This is the keep-alive ping that services
         need to issue in regular intervals if
         <varname>WatchdogSec=</varname> is enabled for it. See
-        <citerefentry><refentrytitle>logind.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+        <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
         for information how to enable this functionality and
         <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
         for the details of how the service can check whether the
         manager will accept messages for a service only if
         <varname>FileDescriptorStoreMax=</varname> is set to non-zero
         for it (defaults to zero). See
-        <citerefentry><refentrytitle>logind.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+        <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
         for details. Multiple arrays of file descriptors may be sent
         in separate messages, in which case the arrays are combined.
         Note that the service manager removes duplicate file
         below.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>FDNAME=...</term>
+
+        <listitem><para>When used in combination with
+        <varname>FDSTORE=1</varname>, specifies a name for the
+        submitted file descriptors. This name is passed to the service
+        during activation, and may be queried using
+        <citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>. File
+        descriptors submitted without this field set, will implicitly
+        get the name <literal>stored</literal> assigned. Note that, if
+        multiple file descriptors are submitted at once, the specified
+        name will be assigned to all of them. In order to assign
+        different names to submitted file descriptors, submit them in
+        separate invocations of
+        <function>sd_pid_notify_with_fds()</function>. The name may
+        consist of any ASCII character, but must not contain control
+        characters or <literal>:</literal>. It may not be longer than
+        255 characters. If a submitted name does not follow these
+        restrictions, it is ignored.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>WATCHDOG_USEC=...</term>
+
+        <listitem><para>Reset <varname>watchdog_usec</varname> value during runtime.
+        Notice that this is not available when using <function>sd_event_set_watchdog()</function>
+        or <function>sd_watchdog_enabled()</function>.
+        Example : <literal>WATCHDOG_USEC=20000000</literal></para></listitem>
+      </varlistentry>
+
     </variablelist>
 
     <para>It is recommended to prefix variable names that are not
     <para>Note that elogind will accept status data sent from a
     service only if the <varname>NotifyAccess=</varname> option is
     correctly set in the service definition file. See
-    <citerefentry><refentrytitle>logind.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+    <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
     for details.</para>
 
     <para><function>sd_notifyf()</function> is similar to
     use as originating PID for the message as first argument. This is
     useful to send notification messages on behalf of other processes,
     provided the appropriate privileges are available. If the PID
-    argument is specified as 0 the process ID of the calling process
+    argument is specified as 0, the process ID of the calling process
     is used, in which case the calls are fully equivalent to
     <function>sd_notify()</function> and
     <function>sd_notifyf()</function>.</para>
 
       <para>To store an open file descriptor in the service manager,
       in order to continue operation after a service restart without
-      losing state use <literal>FDSTORE=1</literal>:</para>
+      losing state, use <literal>FDSTORE=1</literal>:</para>
 
-      <programlisting>sd_pid_notify_with_fds(0, 0, "FDSTORE=1", &amp;fd, 1);</programlisting>
+      <programlisting>sd_pid_notify_with_fds(0, 0, "FDSTORE=1\nFDNAME=foobar", &amp;fd, 1);</programlisting>
     </example>
   </refsect1>
 
   <refsect1>
     <title>See Also</title>
     <para>
-      <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>logind.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index 4ae756a9a5727b6e666189dd68be4a81716b6525..b4d044282d72289df148beae73bdad1d62c0102b 100644 (file)
       <varlistentry>
         <term><constant>-ENODATA</constant></term>
 
-        <listitem><para>Given field is not specified for the described
+        <listitem><para>The given field is not specified for the described
         seat.</para>
         </listitem>
       </varlistentry>
         <term><constant>-EINVAL</constant></term>
 
         <listitem><para>An input parameter was invalid (out of range,
-        or NULL, where that's not accepted).</para></listitem>
+        or NULL, where that is not accepted).</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 11171473b12b013b3ebc5c4ea683d6f31470a672..97721a56a507cd73ec20697d50d69313850337c1 100644 (file)
       <varlistentry>
         <term><constant>-ENODATA</constant></term>
 
-        <listitem><para>Given field is not specified for the described
+        <listitem><para>The given field is not specified for the described
         session.</para>
         </listitem>
       </varlistentry>
         <term><constant>-EINVAL</constant></term>
 
         <listitem><para>An input parameter was invalid (out of range,
-        or NULL, where that's not accepted).</para></listitem>
+        or NULL, where that is not accepted).</para></listitem>
       </varlistentry>
 
       <varlistentry>
index b9670e8bf903a736d1ac9ce524e0b442c9ab1689..19401e6c0203c6d5ef7c92623af2a5ac622db9d2 100644 (file)
 
     <para>To enable service supervision with the watchdog logic, use
     <varname>WatchdogSec=</varname> in service files. See
-    <citerefentry><refentrytitle>logind.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+    <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
     for details.</para>
+
+    <para>Use
+    <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    to enable automatic watchdog support in
+    <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>-based event loops.</para>
   </refsect1>
 
   <refsect1>
     </variablelist>
   </refsect1>
 
-  <refsect1>
-    <title>History</title>
-
-    <para>The watchdog functionality and the
-    <varname>$WATCHDOG_USEC</varname> variable were added in
-    elogind-41.</para>
-
-    <para><function>sd_watchdog_enabled()</function> function was
-    added in elogind-209. Since that version the
-    <varname>$WATCHDOG_PID</varname> variable is also set.</para>
-  </refsect1>
-
   <refsect1>
     <title>See Also</title>
     <para>
-      <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>logind.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index 15268030f8648d5feff3605e6ddba1d02680f5e9..807702493c7c92e9fe319fbf04fd779d7cd01ab8 100644 (file)
@@ -38,9 +38,9 @@
   <refsection id='main-conf'>
     <title>Configuration Directories and Precedence</title>
 
-    <para>Default configuration is defined during compilation, so a
+    <para>The default configuration is defined during compilation, so a
     configuration file is only needed when it is necessary to deviate
-    from those defaults. By default the configuration file in
+    from those defaults. By default, the configuration file in
     <filename>/etc/elogind/</filename> contains commented out entries
     showing the defaults as a guide to the administrator. This file
     can be edited to create local overrides.
index 2efab701033b4bec508d8ce1fae1564be0b780e6..0d1d4b0f9a10c4a44d4f24cd14ce549b86b0b0c9 100644 (file)
@@ -2,5 +2,5 @@ POTFILES
 Makefile.in.in
 .intltool-merge-cache
 Makefile
-elogind.pot
+systemd.pot
 /*.gmo
index 93c5c53023624da9f865d6c9c53b28f39af84b8c..2f1ba199ac2cd98635cc0469c19cdee1cff5c4e4 100644 (file)
@@ -1,18 +1,23 @@
+be
+be@latin
+bg
+da
 de
 el
+es
 fr
 gl
+hr
 hu
+id
 it
 ko
 pl
 pt_BR
 ru
-uk
-sv
 sr
-es
-zh_TW
-be
-be@latin
+sv
 tr
+uk
+zh_CN
+zh_TW
index 51254ec5333f2394a9b099ab9cae34f23b569e9a..b56a9984c4ce655db1c8b4cceea48658c92358c8 100644 (file)
@@ -6,7 +6,6 @@ src/core/dbus-mount.c
 src/core/dbus-path.c
 src/core/dbus-service.c
 src/core/dbus-slice.c
-src/core/dbus-snapshot.c
 src/core/dbus-socket.c
 src/core/dbus-swap.c
 src/core/dbus-target.c
index d682f3202589b74710c6c6524cc981b5b81d4322..2f60eb2ebaf8dc35d843849f904816bc289fcd37 100644 (file)
--- a/po/be.po
+++ b/po/be.po
@@ -3,13 +3,13 @@
 # This file is distributed under the same license as the systemd package.
 #
 #
-# Viktar Vaŭčkievič <victorenator@gmail.com>, 2015.
+# Viktar Vaŭčkievič <victorenator@gmail.com>, 2015, 2016.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-12 13:42+0300\n"
-"PO-Revision-Date: 2015-09-12 16:25+0300\n"
+"POT-Creation-Date: 2016-06-09 19:54+0300\n"
+"PO-Revision-Date: 2016-06-09 19:47+0300\n"
 "Last-Translator: Viktar Vaŭčkievič <victorenator@gmail.com>\n"
 "Language-Team: \n"
 "Language: be\n"
@@ -244,46 +244,57 @@ msgstr ""
 "апрацоўваць закрыццё крышкі ноўтбука."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr ""
+"Дазволіць карыстальніку, якія яшчэ не ўвайшоў у сістэму, выконваць праграмы"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Неабходны відавочны запыт для выканання праграм карыстальніка, які яшчэ не "
+"ўвайшоў у сістэму."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
 msgid "Allow non-logged-in users to run programs"
 msgstr ""
 "Дазволіць карыстальнікам, якія яшчэ не ўвайшлі ў сістэму, выконваць праграмы"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
 "Неабходна аўтэнтыфікацыя для выканання праграм карыстальніка, які яшчэ не "
 "ўвайшоў у сістэму."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
 msgstr "Дазволіць далучаць прылады да працоўных месцаў"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
 msgstr "Неабходна аўтэнтыфікацыя для далучэння прылад да працоўных месцаў."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
 msgstr "Адключаць прылады ад працоўных месцаў"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr "Неабходна аўтэнтыфікацыя для адключэння прылад ад працоўных месцаў."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
 msgstr "Выключыць сістэму"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
 msgstr "Неабходна аўтэнтыфікацыя для выключэння сістэмы."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
 msgstr "Выключыць сістэму пры прысутнасці іншых карыстальнікаў"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
@@ -291,11 +302,11 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для выключэння сістэмы пры прысутнасці іншых "
 "карыстальнікаў."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
 msgstr "Выключыць сістэму, калі праграмы перашкаджаюць гэтаму"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
@@ -303,19 +314,19 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для выключэння сістэмы, калі праграмы перашкаджаюць "
 "гэтаму."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
 msgstr "Перазагрузіць сістэму"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
 msgstr "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
 msgstr "Перазагрузіць сістэму пры прысутнасці іншых карыстальнікаў"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
@@ -323,11 +334,11 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы пры прысутнасці іншых "
 "карыстальнікаў."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
 msgstr "Перазагрузіць сістэму, калі праграмы перашкаджаюць гэтаму"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
@@ -335,19 +346,19 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы, калі праграмы "
 "перашкаджаюць гэтаму."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
 msgstr "Прыпыніць сістэму"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
 msgstr "Неабходна аўтэнтыфікацыя для прыпынення сістэмы."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
 msgstr "Прыпыніць сістэму пры прысутнасці іншых карыстальнікаў"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
@@ -355,11 +366,11 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для прыпынення сістэмы пры прысутнасці іншых "
 "карыстальнікаў."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
 msgstr "Прыпыніць сістэму, калі праграмы перашкаджаюць гэтаму"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
@@ -367,19 +378,19 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для прыпынення сістэмы, калі праграмы перашкаджаюць "
 "гэтаму."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
 msgstr "Гібернаваць сістэму"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
 msgstr "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
 msgstr "Гібернаваць сістэму пры прысутнасці іншых карыстальнікаў"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
@@ -387,11 +398,11 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы пры прысутнасці іншых "
 "карыстальнікаў."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
 msgstr "Гібернаваць сістэму, калі праграмы перашкаджаюць гэтаму"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
@@ -399,44 +410,44 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы, калі праграмы перашкаджаюць "
 "гэтаму."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
 msgstr "Кіраваць актыўнымі сесіямі, карыстальнікамі і працоўнымі месцамі"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
 "Неабходна аўтэнтыфікацыя для кіравання актыўнымі сесіямі, карыстальнікамі і "
 "месцамі."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
 msgstr "Блакаваць або разблакаваць актыўную сесію"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
 msgstr ""
 "Неабходна аўтэнтыфікацыя для блакіроўкі або разблакіроўкі актыўнай сесіі."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
 msgstr "Дазволіць указанне прашыўцы на загрузку інтэрфейсу налад"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
 msgstr ""
 "Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
 msgid "Set a wall message"
 msgstr "Усталяваць усеагульнае паведамленне"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
 msgid "Authentication is required to set a wall message"
-msgstr "Ð\9dеабÑ\85одна Ð°Ñ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f Ð´Ð»Ñ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\83Ñ\81еагÑ\83лÑ\8cнага Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ\8f."
+msgstr "Ð\9dеабÑ\85одна Ð°Ñ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f Ð´Ð»Ñ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\9eÑ\81еагÑ\83лÑ\8cнага Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ\8f"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
@@ -552,30 +563,30 @@ msgstr ""
 "Неабходна аўтэнтыфікацыя для ўключэння або выключэння сінхранізацыі часу па "
 "сетцы."
 
-#: ../src/core/dbus-unit.c:428
+#: ../src/core/dbus-unit.c:450
 msgid "Authentication is required to start '$(unit)'."
 msgstr "Неабходна аўтэнтыфікацыя для запуску '$(unit)'."
 
-#: ../src/core/dbus-unit.c:429
+#: ../src/core/dbus-unit.c:451
 msgid "Authentication is required to stop '$(unit)'."
-msgstr "Неабходна аўтэнтыфікацыя для ."
+msgstr "Неабходна аўтэнтыфікацыя для спынення '$(unit)'."
 
-#: ../src/core/dbus-unit.c:430
+#: ../src/core/dbus-unit.c:452
 msgid "Authentication is required to reload '$(unit)'."
 msgstr "Неабходна аўтэнтыфікацыя для перачытання стану '$(unit)'."
 
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
 msgid "Authentication is required to restart '$(unit)'."
 msgstr "Неабходна аўтэнтыфікацыя для перазапуску '$(unit)'."
 
-#: ../src/core/dbus-unit.c:535
+#: ../src/core/dbus-unit.c:560
 msgid "Authentication is required to kill '$(unit)'."
 msgstr "Неабходна аўтэнтыфікацыя для забойства '$(unit)'."
 
-#: ../src/core/dbus-unit.c:565
+#: ../src/core/dbus-unit.c:590
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'."
 
-#: ../src/core/dbus-unit.c:597
+#: ../src/core/dbus-unit.c:622
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўласцівасцей '$(unit)'."
index 15488b2c8115d397709a846e692eb1cb2f4a6aa1..121696a31681b5144ffd28d67350a337b84fa9aa 100644 (file)
@@ -3,13 +3,13 @@
 # This file is distributed under the same license as the systemd package.
 #
 #
-# Viktar Vaŭčkievič <victorenator@gmail.com>, 2015.
+# Viktar Vaŭčkievič <victorenator@gmail.com>, 2015, 2016.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-12 13:42+0300\n"
-"PO-Revision-Date: 2015-09-12 16:25+0300\n"
+"POT-Creation-Date: 2016-06-09 19:54+0300\n"
+"PO-Revision-Date: 2016-06-09 19:50+0300\n"
 "Last-Translator: Viktar Vaŭčkievič <victorenator@gmail.com>\n"
 "Language-Team: \n"
 "Language: be@latin\n"
@@ -246,48 +246,59 @@ msgstr ""
 "apracoŭvać zakryccio kryški noŭtbuka."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr ""
+"Dazvolić karystaĺniku, jakija jašče nie ŭvajšoŭ u sistemu, vykonvać prahramy"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Nieabchodny vidavočny zapyt dlia vykanannia prahram karystaĺnika, jaki jašče "
+"nie ŭvajšoŭ u sistemu."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
 msgid "Allow non-logged-in users to run programs"
 msgstr ""
 "Dazvolić karystaĺnikam, jakija jašče nie ŭvajšli ŭ sistemu, vykonvać prahramy"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia vykanannia prahram karystaĺnika, jaki jašče "
 "nie ŭvajšoŭ u sistemu."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
 msgstr "Dazvolić dalučać prylady da pracoŭnych miescaŭ"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
 msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia dalučennia prylad da pracoŭnych miescaŭ."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
 msgstr "Adkliučać prylady ad pracoŭnych miescaŭ"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia adkliučennia prylad ad pracoŭnych miescaŭ."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
 msgstr "Vykliučyć sistemu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
 msgstr "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
 msgstr "Vykliučyć sistemu pry prysutnasci inšych karystaĺnikaŭ"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
@@ -295,11 +306,11 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy pry prysutnasci inšych "
 "karystaĺnikaŭ."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
 msgstr "Vykliučyć sistemu, kali prahramy pieraškadžajuć hetamu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
@@ -307,19 +318,19 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy, kali prahramy "
 "pieraškadžajuć hetamu."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
 msgstr "Pierazahruzić sistemu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
 msgstr "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
 msgstr "Pierazahruzić sistemu pry prysutnasci inšych karystaĺnikaŭ"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
@@ -327,11 +338,11 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy pry prysutnasci "
 "inšych karystaĺnikaŭ."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
 msgstr "Pierazahruzić sistemu, kali prahramy pieraškadžajuć hetamu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
@@ -339,19 +350,19 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy, kali prahramy "
 "pieraškadžajuć hetamu."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
 msgstr "Prypynić sistemu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
 msgstr "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
 msgstr "Prypynić sistemu pry prysutnasci inšych karystaĺnikaŭ"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
@@ -359,11 +370,11 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy pry prysutnasci inšych "
 "karystaĺnikaŭ."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
 msgstr "Prypynić sistemu, kali prahramy pieraškadžajuć hetamu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
@@ -371,19 +382,19 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy, kali prahramy "
 "pieraškadžajuć hetamu."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
 msgstr "Hibiernavać sistemu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
 msgstr "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
 msgstr "Hibiernavać sistemu pry prysutnasci inšych karystaĺnikaŭ"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
@@ -391,11 +402,11 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy pry prysutnasci inšych "
 "karystaĺnikaŭ."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
 msgstr "Hibiernavać sistemu, kali prahramy pieraškadžajuć hetamu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
@@ -403,32 +414,32 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy, kali prahramy "
 "pieraškadžajuć hetamu."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
 msgstr "Kiravać aktyŭnymi siesijami, karystaĺnikami i pracoŭnymi miescami"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia kiravannia aktyŭnymi siesijami, "
 "karystaĺnikami i miescami."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
 msgstr "Blakavać abo razblakavać aktyŭnuju siesiju"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
 msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia blakiroŭki abo razblakiroŭki aktyŭnaj "
 "siesii."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
 msgstr "Dazvolić ukazannie prašyŭcy na zahruzku interfiejsu nalad"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
@@ -436,14 +447,14 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia ŭkazannia prašyŭcy na zahruzku interfiejsu "
 "nalad."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
 msgid "Set a wall message"
 msgstr "Ustaliavać usieahuĺnaje paviedamliennie"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
 msgid "Authentication is required to set a wall message"
 msgstr ""
-"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia usieahuĺnaha paviedamliennia."
+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
@@ -563,32 +574,32 @@ msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia ŭkliučennia abo vykliučennia sinchranizacyi "
 "času pa sietcy."
 
-#: ../src/core/dbus-unit.c:428
+#: ../src/core/dbus-unit.c:450
 msgid "Authentication is required to start '$(unit)'."
 msgstr "Nieabchodna aŭtentyfikacyja dlia zapusku '$(unit)'."
 
-#: ../src/core/dbus-unit.c:429
+#: ../src/core/dbus-unit.c:451
 msgid "Authentication is required to stop '$(unit)'."
-msgstr "Nieabchodna aŭtentyfikacyja dlia ."
+msgstr "Nieabchodna aŭtentyfikacyja dlia spyniennia '$(unit)'."
 
-#: ../src/core/dbus-unit.c:430
+#: ../src/core/dbus-unit.c:452
 msgid "Authentication is required to reload '$(unit)'."
 msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu '$(unit)'."
 
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
 msgid "Authentication is required to restart '$(unit)'."
 msgstr "Nieabchodna aŭtentyfikacyja dlia pierazapusku '$(unit)'."
 
-#: ../src/core/dbus-unit.c:535
+#: ../src/core/dbus-unit.c:560
 msgid "Authentication is required to kill '$(unit)'."
 msgstr "Nieabchodna aŭtentyfikacyja dlia zabojstva '$(unit)'."
 
-#: ../src/core/dbus-unit.c:565
+#: ../src/core/dbus-unit.c:590
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia anuliavannia pamylkovaha stanu '$(unit)'."
 
-#: ../src/core/dbus-unit.c:597
+#: ../src/core/dbus-unit.c:622
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr ""
 "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭlascivasciej '$(unit)'."
diff --git a/po/bg.po b/po/bg.po
new file mode 100644 (file)
index 0000000..5f92f8e
--- /dev/null
+++ b/po/bg.po
@@ -0,0 +1,617 @@
+# Bulgarian translation of systemd po-file.
+# Copyright (C) 2016 Alexander Shopov <ash@kambanaria.org>
+# This file is distributed under the same license as the systemd package.
+# Alexander Shopov <ash@kambanaria.org>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: systemd master\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-05-14 13:28+0300\n"
+"PO-Revision-Date: 2016-05-14 13:28+0300\n"
+"Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
+"Language-Team: Bulgarian <dict@ludost.net>\n"
+"Language: bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+msgid "Send passphrase back to system"
+msgstr "Изпращане на паролата към системата"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+msgid ""
+"Authentication is required to send the entered passphrase back to the system."
+msgstr "За изпращане на паролата към системата е необходима идентификация."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+msgid "Manage system services or other units"
+msgstr "Управление на услугите или другите модули"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+msgid "Authentication is required to manage system services or other units."
+msgstr ""
+"За управление на услугите или другите модули е необходима идентификация."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+msgid "Manage system service or unit files"
+msgstr "Управление на файловете за услугите или другите модули"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+msgid "Authentication is required to manage system service or unit files."
+msgstr ""
+"За управление на файловете за услугите или другите модули е необходима "
+"идентификация."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+msgid "Set or unset system and service manager environment variables"
+msgstr ""
+"Задаване или изтриване на променливи на средата за системата и управлението "
+"на услугите"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+msgid ""
+"Authentication is required to set or unset system and service manager "
+"environment variables."
+msgstr ""
+"За задаване или изтриване на променливи на средата за системата и "
+"управлението на услугите е необходима идентификация."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+msgid "Reload the systemd state"
+msgstr "Презареждане на състоянието на systemd"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+msgid "Authentication is required to reload the systemd state."
+msgstr "За презареждане на състоянието на systemd е необходима идентификация."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+msgid "Set host name"
+msgstr "Задаване на име на машината"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+msgid "Authentication is required to set the local host name."
+msgstr "За задаване на име на локалната машина е необходима идентификация."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+msgid "Set static host name"
+msgstr "Задаване на статично име на машината"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+msgid ""
+"Authentication is required to set the statically configured local host name, "
+"as well as the pretty host name."
+msgstr ""
+"За задаване на статично име на локалната машина е необходима идентификация."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+msgid "Set machine information"
+msgstr "Задаване на информация за машината"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+msgid "Authentication is required to set local machine information."
+msgstr ""
+"За задаване на информация за локалната машина е необходима идентификация."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:1
+msgid "Import a VM or container image"
+msgstr "Внасяне на изображение на виртуална машина или контейнер"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:2
+msgid "Authentication is required to import a VM or container image"
+msgstr ""
+"За внасяне на изображение на виртуална машина или контейнер е необходима "
+"идентификация."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:3
+msgid "Export a VM or container image"
+msgstr "Изнасяне на изображение на виртуална машина или контейнер"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:4
+msgid "Authentication is required to export a VM or container image"
+msgstr ""
+"За изнасяне на изображение на виртуална машина или контейнер е необходима "
+"идентификация."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:5
+msgid "Download a VM or container image"
+msgstr "Изтегляне на изображение на виртуална машина или контейнер"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:6
+msgid "Authentication is required to download a VM or container image"
+msgstr ""
+"За изтегляне на изображение на виртуална машина или контейнер е необходима "
+"идентификация."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+msgid "Set system locale"
+msgstr "Задаване на локала на системата"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+msgid "Authentication is required to set the system locale."
+msgstr "За задаване на локала на системата е необходима идентификация."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+msgid "Set system keyboard settings"
+msgstr "Задаване на настройките на клавиатурата"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+msgid "Authentication is required to set the system keyboard settings."
+msgstr "За задаване на настройките на клавиатурата е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:1
+msgid "Allow applications to inhibit system shutdown"
+msgstr "Позволяване на програмите да предотвратяват спирането на системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:2
+msgid ""
+"Authentication is required for an application to inhibit system shutdown."
+msgstr ""
+"За позволяване на програмите да предотвратяват спирането на системата е "
+"необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:3
+msgid "Allow applications to delay system shutdown"
+msgstr "Позволяване на програмите да забавят спирането на системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:4
+msgid "Authentication is required for an application to delay system shutdown."
+msgstr ""
+"За позволяване на програмите да забавят спирането на системата е необходима "
+"идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:5
+msgid "Allow applications to inhibit system sleep"
+msgstr "Позволяване на програмите да предотвратяват приспиването на системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:6
+msgid "Authentication is required for an application to inhibit system sleep."
+msgstr ""
+"За позволяване на програмите да предотвратяват приспиването на системата е "
+"необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:7
+msgid "Allow applications to delay system sleep"
+msgstr "Позволяване на програмите да забавят приспиването на системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:8
+msgid "Authentication is required for an application to delay system sleep."
+msgstr ""
+"За позволяване на програмите да забавят приспиването на системата е "
+"необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:9
+msgid "Allow applications to inhibit automatic system suspend"
+msgstr ""
+"Позволяване на програмите да предотвратяват автоматичното приспиване на "
+"системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:10
+msgid ""
+"Authentication is required for an application to inhibit automatic system "
+"suspend."
+msgstr ""
+"За позволяване на програмите да предотвратяват автоматичното приспиване на "
+"системата е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:11
+msgid "Allow applications to inhibit system handling of the power key"
+msgstr ""
+"Позволяване на програмите да предотвратяват реакцията на системата при "
+"натискане на клавиша за захранване"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:12
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the power key."
+msgstr ""
+"За позволяване на програмите да предотвратяват реакцията на системата при "
+"натискане на клавиша за захранване е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:13
+msgid "Allow applications to inhibit system handling of the suspend key"
+msgstr ""
+"Позволяване на програмите да предотвратяват реакцията на системата при "
+"натискане на клавиша за приспиване"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:14
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the suspend key."
+msgstr ""
+"За позволяване на програмите да предотвратяват реакцията на системата при "
+"натискане на клавиша за приспиване е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:15
+msgid "Allow applications to inhibit system handling of the hibernate key"
+msgstr ""
+"Позволяване на програмите да предотвратяват реакцията на системата при "
+"натискане на клавиша за дълбоко приспиване"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:16
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the hibernate key."
+msgstr ""
+"За позволяване на програмите да предотвратяват реакцията на системата при "
+"натискане на клавиша за дълбоко приспиване е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:17
+msgid "Allow applications to inhibit system handling of the lid switch"
+msgstr ""
+"Позволяване на програмите да предотвратяват реакцията на системата при "
+"затваряне на екрана"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:18
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the lid switch."
+msgstr ""
+"За позволяване на програмите да предотвратяват реакцията на системата при "
+"затваряне на екрана е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr ""
+"Позволяване на потребители, които не са се идентифицирали, да изпълняват "
+"програми"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"За позволяване на потребители, които не са се идентифицирали, да изпълняват "
+"програми е необходима изрична заявка."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow non-logged-in users to run programs"
+msgstr ""
+"Позволяване на потребители, които не са се идентифицирали, да изпълняват "
+"програми"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
+msgid "Authentication is required to run programs as a non-logged-in user."
+msgstr ""
+"За позволяване на потребители, които не са се идентифицирали, да изпълняват "
+"програми е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
+msgid "Allow attaching devices to seats"
+msgstr "Позволяване на закачане на устройства към работните места"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
+msgid "Authentication is required for attaching a device to a seat."
+msgstr ""
+"За позволяване на закачане на устройства към работните места е необходима "
+"идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
+msgid "Flush device to seat attachments"
+msgstr "Изчистване на връзките между устройствата и работните места"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
+msgid ""
+"Authentication is required for resetting how devices are attached to seats."
+msgstr ""
+"За изчистване на връзките между устройствата и работните места е необходима "
+"идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
+msgid "Power off the system"
+msgstr "Изключване на системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
+msgid "Authentication is required for powering off the system."
+msgstr "За изключване на системата е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
+msgid "Power off the system while other users are logged in"
+msgstr "Изключване на системата, дори когато има други вписани потребители"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
+msgid ""
+"Authentication is required for powering off the system while other users are "
+"logged in."
+msgstr ""
+"За изключване на системата, дори когато има други вписани потребители, е "
+"необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
+msgid "Power off the system while an application asked to inhibit it"
+msgstr "Изключване на системата, дори когато програма иска да предотврати това"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
+msgid ""
+"Authentication is required for powering off the system while an application "
+"asked to inhibit it."
+msgstr ""
+"За изключване на системата, дори когато програма иска да предотврати това, е "
+"необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
+msgid "Reboot the system"
+msgstr "Рестартиране на системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
+msgid "Authentication is required for rebooting the system."
+msgstr "За рестартиране на системата е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
+msgid "Reboot the system while other users are logged in"
+msgstr "Рестартиране на системата, дори когато има други вписани потребители"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
+msgid ""
+"Authentication is required for rebooting the system while other users are "
+"logged in."
+msgstr ""
+"За рестартиране на системата, дори когато има други вписани потребители, е "
+"необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
+msgid "Reboot the system while an application asked to inhibit it"
+msgstr ""
+"Рестартиране на системата, дори когато програма иска да предотврати това"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
+msgid ""
+"Authentication is required for rebooting the system while an application "
+"asked to inhibit it."
+msgstr ""
+"За рестартиране на системата, дори когато програма иска да предотврати това, "
+"е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Suspend the system"
+msgstr "Приспиване на системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid "Authentication is required for suspending the system."
+msgstr "За приспиване на системата е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Suspend the system while other users are logged in"
+msgstr "Приспиване на системата, дори когато има други вписани потребители"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for suspending the system while other users are "
+"logged in."
+msgstr ""
+"За приспиване на системата, дори когато има други вписани потребители, е "
+"необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Suspend the system while an application asked to inhibit it"
+msgstr "Приспиване на системата, дори когато програма иска да предотврати това"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid ""
+"Authentication is required for suspending the system while an application "
+"asked to inhibit it."
+msgstr ""
+"За приспиване на системата, дори когато програма иска да предотврати това, е "
+"необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
+msgid "Hibernate the system"
+msgstr "Дълбоко приспиване на системата"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
+msgid "Authentication is required for hibernating the system."
+msgstr "За дълбоко приспиване на системата е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
+msgid "Hibernate the system while other users are logged in"
+msgstr ""
+"Дълбоко приспиване на системата, дори когато има други вписани потребители"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid ""
+"Authentication is required for hibernating the system while other users are "
+"logged in."
+msgstr ""
+"За дълбоко приспиване на системата, дори когато има други вписани "
+"потребители, е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
+msgid "Hibernate the system while an application asked to inhibit it"
+msgstr ""
+"Дълбоко приспиване на системата, дори когато програма иска да предотврати "
+"това"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
+msgid ""
+"Authentication is required for hibernating the system while an application "
+"asked to inhibit it."
+msgstr ""
+"За дълбоко приспиване на системата, дори когато програма иска да предотврати "
+"това, е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
+msgid "Manage active sessions, users and seats"
+msgstr "Управление на работещите сесии, потребители и работни места"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
+msgid ""
+"Authentication is required for managing active sessions, users and seats."
+msgstr ""
+"За управление на работещите сесии, потребители и работни места е необходима "
+"идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
+msgid "Lock or unlock active sessions"
+msgstr "Заключване или отключване на работещите сесии"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid "Authentication is required to lock or unlock active sessions."
+msgstr ""
+"За заключване или отключване на работещите сесии е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Allow indication to the firmware to boot to setup interface"
+msgstr ""
+"Позволяване на заявки към фърмуера да стартира с интерфейса за управление"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid ""
+"Authentication is required to indicate to the firmware to boot to setup "
+"interface."
+msgstr ""
+"За позволяване на заявки към фърмуера да стартира с интерфейса за управление "
+"е необходима идентификация."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
+msgid "Set a wall message"
+msgstr "Задаване на системно съобщение „wall“"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
+msgid "Authentication is required to set a wall message"
+msgstr "За задаване на системно съобщение „wall“ е необходима идентификация."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+msgid "Log into a local container"
+msgstr "Вписване в локален контейнер"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+msgid "Authentication is required to log into a local container."
+msgstr "За вписване в локален контейнер е необходима идентификация."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Вписване в локалната машина"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "За вписване в локалната машина е необходима идентификация."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Достъп до обвивка в локален контейнер"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "За достъп до обвивка в локален контейнер е необходима идентификация."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Достъп до обвивка на локалната машина"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "За достъп до обвивка на локалната машина е необходима идентификация."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Получаване на псевдо терминал в локален контейнер"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+"За получаване на псевдо терминал в локален контейнер е необходима "
+"идентификация."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Получаване на псевдо терминал на локалната машина"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr ""
+"За получаване на псевдо терминал на локалната машина е необходима "
+"идентификация."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "Управление на локалните виртуални машини и контейнери"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+msgid ""
+"Authentication is required to manage local virtual machines and containers."
+msgstr ""
+"За управление на локалните виртуални машини и контейнери е необходима "
+"идентификация."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+msgid "Manage local virtual machine and container images"
+msgstr "Управление на изображения на виртуални машини или контейнери"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+msgid ""
+"Authentication is required to manage local virtual machine and container "
+"images."
+msgstr ""
+"За управление на изображения на виртуални машини или е необходима "
+"идентификация."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+msgid "Set system time"
+msgstr "Задаване на времето на системата"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+msgid "Authentication is required to set the system time."
+msgstr "За задаване на времето на системата е необходима идентификация."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+msgid "Set system timezone"
+msgstr "Задаване на часовия пояс на системата"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+msgid "Authentication is required to set the system timezone."
+msgstr "За задаване на часовия пояс на системата е необходима идентификация."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+msgid "Set RTC to local timezone or UTC"
+msgstr "Превключване на системния часовник между местния часови пояс и UTC"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+msgid ""
+"Authentication is required to control whether the RTC stores the local or "
+"UTC time."
+msgstr ""
+"За превключване на системния часовник между местния часови пояс и UTC е "
+"необходима идентификация."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+msgid "Turn network time synchronization on or off"
+msgstr "Превключване на синхронизацията на времето по мрежата"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+msgid ""
+"Authentication is required to control whether network time synchronization "
+"shall be enabled."
+msgstr ""
+"За превключване на синхронизацията на времето по мрежата е необходима "
+"идентификация."
+
+#: ../src/core/dbus-unit.c:450
+msgid "Authentication is required to start '$(unit)'."
+msgstr "За стартиране на „$(unit)“ е необходима идентификация."
+
+#: ../src/core/dbus-unit.c:451
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "За спиране на „$(unit)“ е необходима идентификация."
+
+#: ../src/core/dbus-unit.c:452
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "За презареждане на „$(unit)“ е необходима идентификация."
+
+#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "За рестартиране на „$(unit)“ е необходима идентификация."
+
+#: ../src/core/dbus-unit.c:560
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "За убиване на „$(unit)“ е необходима идентификация."
+
+#: ../src/core/dbus-unit.c:590
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"За премахване на състоянието за неуспех на „$(unit)“ е необходима "
+"идентификация."
+
+#: ../src/core/dbus-unit.c:622
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "За задаване на свойствата на „$(unit)“ е необходима идентификация."
diff --git a/po/da.po b/po/da.po
new file mode 100644 (file)
index 0000000..a5be579
--- /dev/null
+++ b/po/da.po
@@ -0,0 +1,609 @@
+# Danish translation for systemd.
+# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
+# This file is distributed under the same license as the systemd package.
+# Daniel Machon <dmachon.dev@gmail.com>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: systemd master\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2015-10-07 19:30+0000\n"
+"PO-Revision-Date: 2015-10-07 19:30+0200\n"
+"Last-Translator: Daniel Machon <dmachon.dev@gmail.com>\n"
+"Language-Team: danish\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+msgid "Send passphrase back to system"
+msgstr "Send adgangssætning tilbage til systemet"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+msgid ""
+"Authentication is required to send the entered passphrase back to the system."
+msgstr ""
+"Autentificering er nødvendig for at sende adgangssætning tilbage til systemet."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+msgid "Manage system services or other units"
+msgstr "Håndtér system services eller andre enheder"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+msgid "Authentication is required to manage system services or other units."
+msgstr ""
+"Autentificering er nødvendig for at håndtere system services og andre enheder."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+msgid "Manage system service or unit files"
+msgstr "Håndtér system services eller enhedsfiler"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+msgid "Authentication is required to manage system service or unit files."
+msgstr ""
+"Autentificering er nødvendig for at håndtere system service eller enhedsfiler."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+msgid "Set or unset system and service manager environment variables"
+msgstr ""
+"Sæt eller fjern system- og service-forvalter miljøvariabler"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+msgid ""
+"Authentication is required to set or unset system and service manager "
+"environment variables."
+msgstr "Autentificering er nødvendig for at sætte eller fjerne system- "
+"og service-forvalter miljøvariabler."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+msgid "Reload the systemd state"
+msgstr "Genindlæs systemd tilstand"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+msgid "Authentication is required to reload the systemd state."
+msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+msgid "Set host name"
+msgstr "Sæt værtsnavn"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+msgid "Authentication is required to set the local host name."
+msgstr "Autentificering er nødvendig for at sætte værtsnavn."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+msgid "Set static host name"
+msgstr "Sæt statisk værstnavn"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+msgid ""
+"Authentication is required to set the statically configured local host name, "
+"as well as the pretty host name."
+msgstr ""
+"Autentificering er nødvendig for at sætte det statisk konfigurerede lokale "
+"værtsnavn, lige så vel som det pæne værtsnavn."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+msgid "Set machine information"
+msgstr "Sæt maskininformation."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+msgid "Authentication is required to set local machine information."
+msgstr "Autentificering er nødvendig for at sætte lokal maskininformation."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:1
+msgid "Import a VM or container image"
+msgstr "Importér en VM eller container billede"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:2
+msgid "Authentication is required to import a VM or container image"
+msgstr ""
+"Autentificering er nødvendig for at importére en VM eller "
+"container billeder."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:3
+msgid "Export a VM or container image"
+msgstr "Exportér en VM eller container billede"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:4
+msgid "Authentication is required to export a VM or container image"
+msgstr "Autentificering er nødvendig for at exportére en VM eller container billede"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:5
+msgid "Download a VM or container image"
+msgstr "Hent en VM eller container billede"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:6
+msgid "Authentication is required to download a VM or container image"
+msgstr "Autentificering er nødvendig for at hente en VM eller container billede"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+msgid "Set system locale"
+msgstr "Sæt sprogindstillinger for systemet"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+msgid "Authentication is required to set the system locale."
+msgstr ""
+"Autentificering er nødvendig for at sætte sprogindstillinger "
+"for systemet."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+msgid "Set system keyboard settings"
+msgstr "Sæt tastaturindstillinger for systemet."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+msgid "Authentication is required to set the system keyboard settings."
+msgstr ""
+"Autentificering er nødvendig for at sætte tastaturindstillinger "
+"for systemet."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:1
+msgid "Allow applications to inhibit system shutdown"
+msgstr "Tillad applikationer at hæmme system nedlukning"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:2
+msgid ""
+"Authentication is required for an application to inhibit system shutdown."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme "
+"system nedlukning."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:3
+msgid "Allow applications to delay system shutdown"
+msgstr "Tillad applikationer at forsinke system nedlukning"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:4
+msgid "Authentication is required for an application to delay system shutdown."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan forsinke "
+"system nedlukning."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:5
+msgid "Allow applications to inhibit system sleep"
+msgstr "Tillad applikationer at hæmme system dvale"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:6
+msgid "Authentication is required for an application to inhibit system sleep"
+msgstr "Autentificering er nødvendig for at en applikation kan hæmme system dvale"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:7
+msgid "Allow applications to delay system sleep"
+msgstr "Tillad applikationer at forsinke system dvale"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:8
+msgid "Authentication is required for an application to delay system sleep."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan forsinke system "
+"dvale."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:9
+msgid "Allow applications to inhibit automatic system suspend"
+msgstr "Tillad applikationer at hæmme automatisk system standby"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:10
+msgid ""
+"Authentication is required for an application to inhibit automatic system "
+"suspend."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme automatisk "
+"system standby."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:11
+msgid "Allow applications to inhibit system handling of the power key"
+msgstr "Tillad applikationer at hæmme systemhåndtering af tænd/sluk-knappen"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:12
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the power key."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
+"af tænd/sluk-knappen."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:13
+msgid "Allow applications to inhibit system handling of the suspend key"
+msgstr "Tillad applikationer at hæmme systemhåndtering af standby-knappen"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:14
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the suspend key."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
+"af standby-knappen."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:15
+msgid "Allow applications to inhibit system handling of the hibernate key"
+msgstr "Tillad applikationer at hæmme systemhåndtering af dvale-knappen"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:16
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the hibernate key."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme "
+"systemhåndtering af dvale-knappen."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:17
+msgid "Allow applications to inhibit system handling of the lid switch"
+msgstr ""
+"Tillad applikationer at hæmme systemhåndtering af skærmlukning"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:18
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the lid switch."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
+"af skærmlukning."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in users to run programs"
+msgstr "Tillad brugere der ikke er logget ind, at køre programmer"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Authentication is required to run programs as a non-logged-in user."
+msgstr ""
+"Autentificering er nødvendig for at brugere, som ikke er logget ind, kan "
+"køre programmer."
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow attaching devices to seats"
+msgstr "Tillad at montere af enheder til arbejdsstationer"
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
+msgid "Authentication is required for attaching a device to a seat."
+msgstr ""
+"Autentificering er nødvendig for at montere en enhed til en "
+"arbejdsstation."
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
+msgid "Flush device to seat attachments"
+msgstr "Nulstil enhed monteret til en arbejdsstation"
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
+msgid ""
+"Authentication is required for resetting how devices are attached to seats."
+msgstr ""
+"Autentificering er nødvendig for at nulstille måden enheder er monteret "
+"arbejdsstationer."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
+msgid "Power off the system"
+msgstr "Sluk for systemet"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
+msgid "Authentication is required for powering off the system."
+msgstr "Autentificering er nødvendig for at slukke systemet"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
+msgid "Power off the system while other users are logged in"
+msgstr "Sluk systemet mens andre brugere er logget på"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
+msgid ""
+"Authentication is required for powering off the system while other users are "
+"logged in."
+msgstr ""
+"Autentificering er nødvendig for at slukke systemet mens andre brugere "
+"er logget på."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
+msgid "Power off the system while an application asked to inhibit it"
+msgstr ""
+"Sluk for systemet mens en applikation har forespurgt at hæmme det"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
+msgid ""
+"Authentication is required for powering off the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificering er nødvendig for at slukke systemet mens en applikation har "
+"forespurgt at hæmme det."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
+msgid "Reboot the system"
+msgstr "Genstart systemet"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
+msgid "Authentication is required for rebooting the system."
+msgstr "Autentificering er nødvendig for at genstarte systemet."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
+msgid "Reboot the system while other users are logged in"
+msgstr "Genstart systemet mens andre brugere er logget ind"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
+msgid ""
+"Authentication is required for rebooting the system while other users are "
+"logged in."
+msgstr ""
+"Autentificering er nødvendig for at genstarte systemet mens andre brugere "
+"er logget ind."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
+msgid "Reboot the system while an application asked to inhibit it"
+msgstr ""
+"Genstart systemet mens en applikation har forespurgt at hæmme det"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
+msgid ""
+"Authentication is required for rebooting the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificering er nødvendig for at genstarte systemet mens en applikation "
+"har forespurgt at hæmme det."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
+msgid "Suspend the system"
+msgstr "Sæt systemet på standby"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
+msgid "Authentication is required for suspending the system."
+msgstr "Autentificering er nødvendig for at sætte systemet på standby"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Suspend the system while other users are logged in"
+msgstr "Sæt systemet på standby mens andre brugere er logget på"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid ""
+"Authentication is required for suspending the system while other users are "
+"logged in."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet på standby, mens andre "
+"brugere er logget på."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Suspend the system while an application asked to inhibit it"
+msgstr ""
+"Sæt systemet på standby mens en applikation har forespurgt at hæmme"
+"det"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for suspending the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet på standby, mens en "
+"applikation har forespurgt at hæmme det."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Hibernate the system"
+msgstr "Sæt systemet i dvale"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid "Authentication is required for hibernating the system."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet i dvale-tilstand."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
+msgid "Hibernate the system while other users are logged in"
+msgstr ""
+"Sæt systemet i dvale-tilstand mens andre brugere er logget på"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
+msgid ""
+"Authentication is required for hibernating the system while other users are "
+"logged in."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet i dvale-tilstand, mens "
+"andre brugere er logget på."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
+msgid "Hibernate the system while an application asked to inhibit it"
+msgstr "Sæt systemet i dvale-tilstand mens en applikation har forespurgt at "
+"hæmme det"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid ""
+"Authentication is required for hibernating the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet i dvale tilstand, mens "
+"en applikation har forespurgt at hæmme det."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
+msgid "Manage active sessions, users and seats"
+msgstr "Håndtér aktive sessioner, brugere og arbejdsstationer"
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
+msgid ""
+"Authentication is required for managing active sessions, users and seats."
+msgstr ""
+"Autentificering er nødvendig for at håndtere aktive sessioner, brugere "
+"og arbejdsstationer."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
+msgid "Lock or unlock active sessions"
+msgstr "Lås eller oplås aktive sessioner"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
+msgid "Authentication is required to lock or unlock active sessions."
+msgstr ""
+"Autentificering er nødvendig for at låse eller oplåse aktive sessioner."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
+msgid "Allow indication to the firmware to boot to setup interface"
+msgstr "Tillad meddelelse til firmwaren om at starte op i opsætningsgrænseflade"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid ""
+"Authentication is required to indicate to the firmware to boot to setup "
+"interface."
+msgstr "Autentificering er nødvendig for at meddele firmwaren om at starte "
+"op i opsætningsgrænseflade."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Sæt broadcast-besked"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "Autentificering er nødvendig for at sætte en broadcast-besked"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+msgid "Log into a local container"
+msgstr "Log på en lokal container"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+msgid "Authentication is required to log into a local container."
+msgstr "Autentificering er nødvendig for at logge på en lokal container."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Log på den lokale vært"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "Auitentificering er nødvendig for at logge på den lokale vært."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Anskaf en shell i en lokal container"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr ""
+"Autentificering er nødvendig for at anskaffe en shell i en lokal "
+"container."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Anskaf en shell på den lokale vært"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr ""
+"Autentificering er nødvendig for at anskaffe en shell på den lokale vært."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Anskaf en pseudo-TTY i en lokal container"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+"Autentificering er nødvendig for at anskaffe en pseudo-TTY i en lokal "
+"container."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Anskaf en pseudo-TTY på den lokale vært"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr ""
+"Autentificering er nødvendig for at anskaffe en pseudo-TTY på den "
+"lokale vært."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "Håndtér lokale virtuelle maskiner og containere"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+msgid ""
+"Authentication is required to manage local virtual machines and containers."
+msgstr ""
+"Autentificering er nødvendig for at håndtere lokale virtuelle maskiner og "
+"containere."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+msgid "Manage local virtual machine and container images"
+msgstr "Håndtér lokal virtuel maskine- og container billeder"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+msgid ""
+"Authentication is required to manage local virtual machine and container "
+"images."
+msgstr ""
+"Autentificering er nødvendig for at håndtere lokal virtuel maskine- og "
+"container billeder."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+msgid "Set system time"
+msgstr "Sæt tiden for systemet"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+msgid "Authentication is required to set the system time."
+msgstr "Autentificering er nødvendig for at sætte tiden for systemet."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+msgid "Set system timezone"
+msgstr "Sæt tidszone for systemet"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+msgid "Authentication is required to set the system timezone."
+msgstr "Autentificering er nødvendig for at sætte tidszonen for systemet."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+msgid "Set RTC to local timezone or UTC"
+msgstr "Sæt RTC til lokal tidszone eller UTC"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+msgid ""
+"Authentication is required to control whether the RTC stores the local or "
+"UTC time."
+msgstr ""
+"Autentificering er nødvendig for at kontrollere hvorvidt RTC'en gemmer "
+"den lokale tid eller UTC tid."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+msgid "Turn network time synchronization on or off"
+msgstr "Slå synkronisering af netværkstid til eller fra"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+msgid ""
+"Authentication is required to control whether network time synchronization "
+"shall be enabled."
+msgstr ""
+"Autentificering er nødvendig for at kontrollere hvorvidt synkronisering af "
+"netværkstid skal aktiveres"
+
+#: ../src/core/dbus-unit.c:428
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Autentificering er nødvendig for at starte '$(unit)'."
+
+#: ../src/core/dbus-unit.c:429
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Autentificering er nødvendig for at stoppe '$(unit)'."
+
+#: ../src/core/dbus-unit.c:430
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Autentificering er nødvendig for at genindlæse '$(unit)'."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Autentificering at nødvendig for at genstarte '$(unit)'."
+
+#: ../src/core/dbus-unit.c:535
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Autentificering er nødvendig for at eliminere '$(unit)'."
+
+#: ../src/core/dbus-unit.c:565
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på '$(unit)'."
+
+#: ../src/core/dbus-unit.c:597
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr ""
+"Autentificering er nødvendig for at sætte egenskaber på '$(unit)'."
+
+#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+#~ msgstr ""
+#~ "Tryk Ctrl-C for at annulere alle igangværende kontrolleringer af "
+#~ "filsystemet"
+
+#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+#~ msgstr[0] "Igangværende kontrollering på %d disk (%3.1f%% færdig)"
+#~ msgstr[1] "Igangværende kontrollering på %d diske (%3.1f%% færdig)"
index 95cde045b62c938413ac1bad361cb42659ebe25c..94c9986d60473708fd2788ea4f1f1abfbc7e7d90 100644 (file)
--- a/po/el.po
+++ b/po/el.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
 "PO-Revision-Date: 2014-04-29 09:17+0300\n"
 "Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) <dmtrs32@gmail.com>\n"
 "Language-Team: team@lists.gnome.gr\n"
@@ -451,6 +451,15 @@ msgid ""
 "interface."
 msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#, fuzzy
+msgid "Authentication is required to set a wall message"
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr ""
@@ -461,20 +470,68 @@ msgid "Authentication is required to log into a local container."
 msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Manage local virtual machines and containers"
+msgid "Log into the local host"
 msgstr ""
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
 #, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#, fuzzy
+msgid "Acquire a shell in a local container"
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#, fuzzy
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+#, fuzzy
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#, fuzzy
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#, fuzzy
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+#, fuzzy
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+#, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
 msgstr ""
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 #, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machine and container "
@@ -520,3 +577,38 @@ msgid ""
 msgstr ""
 "Απαιτείται πιστοποίηση για να ελέγξετε αν ο συγχρονισμός ώρας δικτύου θα "
 "ενεργοποιηθεί."
+
+#: ../src/core/dbus-unit.c:428
+#, fuzzy
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+
+#: ../src/core/dbus-unit.c:429
+#, fuzzy
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+
+#: ../src/core/dbus-unit.c:430
+#, fuzzy
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#, fuzzy
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+
+#: ../src/core/dbus-unit.c:535
+#, fuzzy
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/core/dbus-unit.c:565
+#, fuzzy
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/core/dbus-unit.c:597
+#, fuzzy
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
index ceca42386a9be24acbbf7b2a5a26fe8c92e8da51..6642351f68380b2022406b50d4bc46f4262bcf23 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -9,16 +9,16 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-04-24 13:26+0200\n"
-"Last-Translator: Álex Puchades <alex94puchades@gmail.com>\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
+"PO-Revision-Date: 2016-06-07 15:41-0400\n"
+"Last-Translator: Pablo Lezaeta Reyes <prflr88@gmail.com>\n"
 "Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n"
 "Language: es\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Gtranslator 2.91.7\n"
+"X-Generator: Poedit 1.8.7.1\n"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
 msgid "Send passphrase back to system"
@@ -72,11 +72,11 @@ msgstr "Se requiere autenticación para recargar el estado de systemd."
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
 msgid "Set host name"
-msgstr "Establecer nombre del equipo"
+msgstr "Establecer el nombre del equipo"
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
 msgid "Authentication is required to set the local host name."
-msgstr "Se requiere autenticación para establecer el nombre de equipo local."
+msgstr "Se requiere autenticación para establecer el nombre del equipo local."
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
 msgid "Set static host name"
@@ -135,7 +135,7 @@ msgstr "Establecer región del sistema"
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
 msgid "Authentication is required to set the system locale."
-msgstr "Se requiere autenticación para establecer la región del sistema"
+msgstr "Se requiere autenticación para establecer la región del sistema."
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
 msgid "Set system keyboard settings"
@@ -412,7 +412,7 @@ msgid ""
 "asked to inhibit it."
 msgstr ""
 "Se requiere autenticación para hibernar el sistema a pesar de que una "
-"aplicación lo impide"
+"aplicación lo impide."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Manage active sessions, users and seats"
@@ -446,6 +446,14 @@ msgstr ""
 "Se requiere autenticación para indicar al firmware que arranque la interfaz "
 "de configuración."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Establecer muro de texto"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "Se requiere autenticación para establecer un muro de texto"
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Conectarse a un contenedor local"
@@ -455,27 +463,74 @@ msgid "Authentication is required to log into a local container."
 msgstr "Se requiere autenticación para conectarse a un contenedor local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Conectarse al equipo local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "Se requiere autenticación para conectarse al equipo local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Se adquiere un intérprete de órdenes en un contenedor local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr ""
+"Se requiere autenticación para adquirir un intérprete de órdenes en un "
+"contenedor local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Se adquiere un intérprete de órdenes en el equipo local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr ""
+"Se requiere autenticación para adquirir un intérprete de órdenes del equipo "
+"local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Se adquiere un seudo-TTY en el contenedor local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+"Se requiere autenticación para adquirir un seudo-TTY en el contenedor local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Se adquiere un seudo-TTY en el equipo local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr ""
+"Se requiere autenticación para adquirir un seudo-TTY en el equipo local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
 msgstr "Administrar máquinas virtuales y contenedores locales"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr ""
 "Se requiere autenticación para administrar las máquinas virtuales y los "
 "contenedores locales."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
-msgstr "Administrar imágenes de máquina virtual y de contenedor locales"
+msgstr "Administrar imágenes de máquina virtual y de contenedores locales"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
 msgstr ""
 "Se requiere autenticación para administrar las imágenes de máquina virtual y "
-"de contenedor locales."
+"de contenedores locales."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
 msgid "Set system time"
@@ -503,7 +558,7 @@ msgid ""
 "UTC time."
 msgstr ""
 "Se requiere autenticación para establecer el reloj del sistema en formato de "
-"hora local / tiempo UTC."
+"hora local o tiempo UTC."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
 msgid "Turn network time synchronization on or off"
@@ -517,6 +572,35 @@ msgstr ""
 "Se requiere autenticación para activar/desactivar la sincronización de hora "
 "por red."
 
+#: ../src/core/dbus-unit.c:428
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Se requiere autenticación para iniciar '$(unit)'."
+
+#: ../src/core/dbus-unit.c:429
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Se requiere autenticación para detener '$(unit)'."
+
+#: ../src/core/dbus-unit.c:430
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Se requiere autenticación para recargar '$(unit)'."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Se requiere autenticación para reiniciar '$(unit)'."
+
+#: ../src/core/dbus-unit.c:535
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Se requiere autenticación para matar a '$(unit)'."
+
+#: ../src/core/dbus-unit.c:565
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Se requiere autenticación para reiniciar el estado de «fallido» de '$(unit)'."
+
+#: ../src/core/dbus-unit.c:597
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr ""
+"Se requiere autenticación para establecer las propiedades de '$(unit)'."
+
 #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
 #~ msgstr ""
 #~ "Presione Ctrl+C para cancelar todas las comprobaciones del sistema de "
index 96cdc7e774dfaab4a7981cdaf2eb4a6e2edab64c..17550c755ec65903ea30b1933a8e2ec693b28643 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -1,13 +1,13 @@
 # French translations for systemd package
 # Traductions françaises du paquet systemd.
 # This file is distributed under the same license as the systemd package.
-# Sylvain Plantefève <sylvain.plantefeve@gmail.com>, 2013-2015
+# Sylvain Plantefève <sylvain.plantefeve@gmail.com>, 2013-2016
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-21 20:11+0200\n"
+"POT-Creation-Date: 2016-04-24 21:13+0200\n"
 "PO-Revision-Date: 2014-12-28 13:04+0100\n"
 "Last-Translator: Sylvain Plantefève <sylvain.plantefeve@gmail.com>\n"
 "Language-Team: French\n"
@@ -254,48 +254,58 @@ msgstr ""
 "gestion par le système du rabat de l'écran."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr "Permet à un utilisateur non connecté d'exécuter des programmes"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Requête explicite requise pour exécuter des programmes en tant "
+"qu'utilisateur non connecté."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
 msgid "Allow non-logged-in users to run programs"
 msgstr "Permet aux utilisateurs non connectés d'exécuter des programmes"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
-"Authentification requise pour permettre aux utilisateurs non connectés "
-"d'exécuter des programmes."
+"Authentification requise pour exécuter des programmes en tant qu'utilisateur "
+"non connecté."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
 msgstr "Permet d'associer des périphériques à des postes (seats)"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
 msgstr ""
 "Authentification requise pour associer un périphérique à un poste (seat)."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
 msgstr "Révoquer les associations de périphériques aux postes (seats)"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr ""
 "Authentification requise pour révoquer les associations de périphériques aux "
 "postes (seats)."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
 msgstr "Éteindre le système"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
 msgstr "Authentification requise pour éteindre le système."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
 msgstr "Éteindre le système alors que d'autres utilisateurs sont connectés"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
@@ -303,11 +313,11 @@ msgstr ""
 "Authentification requise pour éteindre le système alors que d'autres "
 "utilisateurs sont connectés."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
 msgstr "Éteindre le système alors qu'une application a demandé de l'empêcher"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
@@ -315,19 +325,19 @@ msgstr ""
 "Authentification requise pour éteindre le système alors qu'une application a "
 "demandé de l'empêcher."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
 msgstr "Redémarrer le système"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
 msgstr "Authentification requise pour redémarrer le système."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
 msgstr "Redémarrer le système alors que d'autres utilisateurs sont connectés"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
@@ -335,11 +345,11 @@ msgstr ""
 "Authentification requise pour redémarrer le système alors que d'autres "
 "utilisateurs sont connectés."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
 msgstr "Redémarrer le système alors qu'une application a demandé de l'empêcher"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
@@ -347,20 +357,20 @@ msgstr ""
 "Authentification requise pour redémarrer le système alors qu'une application "
 "a demandé de l'empêcher."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
 msgstr "Mettre le système en veille"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
 msgstr "Authentification requise pour mettre le système en veille."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
 msgstr ""
 "Mettre le système en veille alors que d'autres utilisateurs sont connectés"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
@@ -368,12 +378,12 @@ msgstr ""
 "Authentification requise pour mettre le système en veille alors que d'autres "
 "utilisateurs sont connectés."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
 msgstr ""
 "Mettre le système en veille alors qu'une application a demandé de l'empêcher"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
@@ -381,21 +391,21 @@ msgstr ""
 "Authentification requise pour mettre le système en veille alors qu'une "
 "application a demandé de l'empêcher."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
 msgstr "Mettre le système en hibernation"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
 msgstr "Authentification requise pour mettre le système en hibernation."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
 msgstr ""
 "Mettre le système en hibernation alors que d'autres utilisateurs sont "
 "connectés"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
@@ -403,13 +413,13 @@ msgstr ""
 "Authentification requise pour mettre le système en hibernation alors que "
 "d'autres utilisateurs sont connectés."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
 msgstr ""
 "Mettre le système en hibernation alors qu'une application a demandé de "
 "l'empêcher"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
@@ -417,34 +427,34 @@ msgstr ""
 "Authentification requise pour mettre le système en hibernation alors qu'une "
 "application a demandé de l'empêcher."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
 msgstr "Gérer les sessions actives, les utilisateurs et les postes (seats)"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
 "Authentification requise pour gérer les sessions actives, les utilisateurs "
 "et les postes (seats)."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
 msgstr "Verrouiller ou déverrouiller des sessions actives"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
 msgstr ""
 "Authentification requise pour verrouiller ou déverrouiller des sessions "
 "actives."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
 msgstr ""
 "Permet d'indiquer au micrologiciel de démarrer sur l'interface de "
 "configuration"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
@@ -452,11 +462,11 @@ msgstr ""
 "Authentification requise pour indiquer au micrologiciel de démarrer sur "
 "l'interface de configuration."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
 msgid "Set a wall message"
 msgstr "Définir un message wall"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
 msgid "Authentication is required to set a wall message"
 msgstr "Authentification requise pour définir un message wall."
 
@@ -581,33 +591,33 @@ msgstr ""
 "Authentification requise pour activer ou désactiver la synchronisation de "
 "l'heure avec le réseau."
 
-#: ../src/core/dbus-unit.c:428
+#: ../src/core/dbus-unit.c:450
 msgid "Authentication is required to start '$(unit)'."
 msgstr "Authentification requise pour démarrer « $(unit) »."
 
-#: ../src/core/dbus-unit.c:429
+#: ../src/core/dbus-unit.c:451
 msgid "Authentication is required to stop '$(unit)'."
 msgstr "Authentification requise pour arrêter « $(unit) »."
 
-#: ../src/core/dbus-unit.c:430
+#: ../src/core/dbus-unit.c:452
 msgid "Authentication is required to reload '$(unit)'."
 msgstr "Authentification requise pour recharger « $(unit) »."
 
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
 msgid "Authentication is required to restart '$(unit)'."
 msgstr "Authentification requise pour redémarrer « $(unit) »."
 
-#: ../src/core/dbus-unit.c:535
+#: ../src/core/dbus-unit.c:560
 msgid "Authentication is required to kill '$(unit)'."
 msgstr "Authentification requise pour tuer « $(unit) »."
 
-#: ../src/core/dbus-unit.c:565
+#: ../src/core/dbus-unit.c:590
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr ""
 "Authentification requise pour réinitialiser l'état d'« échec » de "
 "« $(unit) »."
 
-#: ../src/core/dbus-unit.c:597
+#: ../src/core/dbus-unit.c:622
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr "Authentification requise pour définir des propriétés de « $(unit) »."
 
diff --git a/po/hr.po b/po/hr.po
new file mode 100644 (file)
index 0000000..a0aff43
--- /dev/null
+++ b/po/hr.po
@@ -0,0 +1,570 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# gogo <trebelnik2@gmail.com>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: systemd master\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2016-27-04 11:57+0100\n"
+"PO-Revision-Date: 2016-04-27 12:11+0200\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.7.1\n"
+"Last-Translator: gogo <trebelnik2@gmail.com>com>\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"Language: hr\n"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+msgid "Send passphrase back to system"
+msgstr "Pošalji lozinku natrag u sustav"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+msgid ""
+"Authentication is required to send the entered passphrase back to the system."
+msgstr "Potrebna je ovjera za slanje upisane lozinke natrag u sustav."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+msgid "Manage system services or other units"
+msgstr "Upravljajte uslugama sustava ili drugim jedinicama"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+msgid "Authentication is required to manage system services or other units."
+msgstr "Potrebna je ovjera za upravljanje uslugama sustava ili jedinicama."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+msgid "Manage system service or unit files"
+msgstr "Upravljajte uslugama sustava ili datotekama jedinica"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+msgid "Authentication is required to manage system service or unit files."
+msgstr ""
+"Potrebna je ovjera za upravljanje uslugama sustava ili datotekama jedinica."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+msgid "Set or unset system and service manager environment variables"
+msgstr "Postavite ili uklonite varijable okruženja sustava i usluga"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+msgid ""
+"Authentication is required to set or unset system and service manager "
+"environment variables."
+msgstr ""
+"Potrebna je ovjera za postavljanje ili uklanjanje varijabla okruženja "
+"sustava i usluga."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+msgid "Reload the systemd state"
+msgstr "Ponovno učitaj systemd stanje"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+msgid "Authentication is required to reload the systemd state."
+msgstr "Potrebna je ovjera za ponovno učitavanje systemd stanja."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+msgid "Set host name"
+msgstr "Postavi naziv računala"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+msgid "Authentication is required to set the local host name."
+msgstr "Potrebna je ovjera za postavljanje naziva lokalnog računala."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+msgid "Set static host name"
+msgstr "Postavi nepromjenjivi naziv račumala"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+msgid ""
+"Authentication is required to set the statically configured local host name, "
+"as well as the pretty host name."
+msgstr ""
+"Potrebna je ovjera za postavljenje nepromjenjivog naziva lokalnog računala, "
+"kao i prijatnog naziva računala."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+msgid "Set machine information"
+msgstr "Postavi informacije računala"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+msgid "Authentication is required to set local machine information."
+msgstr "Potrebna je ovjera za postavljanje informacije lokalnog računala."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:1
+msgid "Import a VM or container image"
+msgstr "Uvezi VM ili spremnik slike"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:2
+msgid "Authentication is required to import a VM or container image"
+msgstr "Potrebna je ovjera za uvoz WM ili spremnika slike"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:3
+msgid "Export a VM or container image"
+msgstr "Izvezi VM ili spremnik slike"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:4
+msgid "Authentication is required to export a VM or container image"
+msgstr "Potrebna je ovjera za izvoz WM ili spremnika slike"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:5
+msgid "Download a VM or container image"
+msgstr "Preuzmi VM ili spremnik slike"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:6
+msgid "Authentication is required to download a VM or container image"
+msgstr "Potrebna je ovjera za preuzimanje VM ili spremnika slike."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+msgid "Set system locale"
+msgstr "Postavi sustav lokalizacije"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+msgid "Authentication is required to set the system locale."
+msgstr "Potrebna je ovjera za postavljanje sustava lokalizacije."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+msgid "Set system keyboard settings"
+msgstr "Postavi postavke tipkovnice sustava"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+msgid "Authentication is required to set the system keyboard settings."
+msgstr "Potrebna je ovjera za postavljanje postavki tipkovnice sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:1
+msgid "Allow applications to inhibit system shutdown"
+msgstr "Dopusti aplikacijama zaustavljanje isključivanja sustava"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:2
+msgid ""
+"Authentication is required for an application to inhibit system shutdown."
+msgstr ""
+"Potrebna je ovjera za dopuštanje aplikacijama zaustavljanje isključivanja "
+"sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:3
+msgid "Allow applications to delay system shutdown"
+msgstr "Dopusti aplikacijama odgodu isključivanja sustava"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:4
+msgid "Authentication is required for an application to delay system shutdown."
+msgstr ""
+"Potrebna je ovjera za dopuštanje aplikacijama odgode isključivanja sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:5
+msgid "Allow applications to inhibit system sleep"
+msgstr "Dopusti aplikacijama zaustavljanje spavanja sustava"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:6
+msgid "Authentication is required for an application to inhibit system sleep."
+msgstr ""
+"Potrebna je ovjera za dopuštanje aplikacijama zaustavljanja spavanja sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:7
+msgid "Allow applications to delay system sleep"
+msgstr "Dopusti aplikacijama odgodu spavanja sustava"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:8
+msgid "Authentication is required for an application to delay system sleep."
+msgstr "Potrebna je ovjera za odgodu spavanja sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:9
+msgid "Allow applications to inhibit automatic system suspend"
+msgstr "Dopusti aplikacijama zaustavljanje automatskog suspendiranja sustava"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:10
+msgid ""
+"Authentication is required for an application to inhibit automatic system "
+"suspend."
+msgstr ""
+"Potrebna je ovjera za dopuštanje aplikacijama zaustavljanje automatskog "
+"suspendiranja sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:11
+msgid "Allow applications to inhibit system handling of the power key"
+msgstr ""
+"Dopusti aplikacijama sprječavanje rukovanja sustava tipkom isključivanja"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:12
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the power key."
+msgstr ""
+"Potrebna je ovjera za dopuštanje aplikacijama sprječavanje rukovanja sustava "
+"tipkom isključivanja."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:13
+msgid "Allow applications to inhibit system handling of the suspend key"
+msgstr "Dopusti aplikacijama sprječavanje rukovanja sustava tipkom suspenzije"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:14
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the suspend key."
+msgstr ""
+"Potrebna je ovjera za dopuštanje aplikacijama sprječavanje rukovanja sustava "
+"tipkom suspenzije."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:15
+msgid "Allow applications to inhibit system handling of the hibernate key"
+msgstr "Dopusti aplikacijama sprječavanje rukovanja sustava tipkom hibernacije"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:16
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the hibernate key."
+msgstr ""
+"Potrebna je ovjera za dopuštanje aplikacijama sprječavanje rukovanja sustava "
+"tipkom hibernacije."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:17
+msgid "Allow applications to inhibit system handling of the lid switch"
+msgstr "Dopusti aplikacijama sprječavanje rukovanja sustava preklopnicama"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:18
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the lid switch."
+msgstr ""
+"Potrebna je ovjera za dopuštenje sprječavanja rukovanja sustava "
+"preklopnicama."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in users to run programs"
+msgstr "Dopusti neprijavljenim korisnicima pokretanje programa"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Authentication is required to run programs as a non-logged-in user."
+msgstr ""
+"Potrebna je ovjera za dopuštenje neprijavljenim korisnicima pokretanje "
+"programa."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow attaching devices to seats"
+msgstr "Dopusti povezivanje uređaja skupu sesija i hardvera"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
+msgid "Authentication is required for attaching a device to a seat."
+msgstr "Potrebna je ovjera za povezivanje uređaja sa skupom sesija i hardvera."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
+msgid "Flush device to seat attachments"
+msgstr "Ukloni povezani uređaj sa skupa sesija i hardvera"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
+msgid ""
+"Authentication is required for resetting how devices are attached to seats."
+msgstr ""
+"Potrebna je ovjera za obnovu povezivanja uređaja sa skupom sesija i hardvera."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
+msgid "Power off the system"
+msgstr "Isključi sustav"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
+msgid "Authentication is required for powering off the system."
+msgstr "Potrebna je ovjera za isključivanje sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
+msgid "Power off the system while other users are logged in"
+msgstr "Isključi sustav kada su ostali korisnici prijavljeni"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
+msgid ""
+"Authentication is required for powering off the system while other users are "
+"logged in."
+msgstr ""
+"Potrebna je ovjera za isključivanje sustava kada su ostali korisnici "
+"prijavljeni."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
+msgid "Power off the system while an application asked to inhibit it"
+msgstr ""
+"Isključi sustav kada je aplikacija zatražila zaustavljanje isključivanja"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
+msgid ""
+"Authentication is required for powering off the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Potrebna je ovjera za isključivanje sustava kada je aplikacija zatražila "
+"zaustavljanje isključivanja."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
+msgid "Reboot the system"
+msgstr "Ponovno pokreni sustav"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
+msgid "Authentication is required for rebooting the system."
+msgstr "Potrebna je ovjera za ponovno pokretanje sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
+msgid "Reboot the system while other users are logged in"
+msgstr "Ponovno pokreni sustav kada su ostali korisnici prijavljeni"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
+msgid ""
+"Authentication is required for rebooting the system while other users are "
+"logged in."
+msgstr ""
+"Potrebna je ovjera za ponovno pokretanje sustava kada su ostali korisnici "
+"prijavljeni."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
+msgid "Reboot the system while an application asked to inhibit it"
+msgstr ""
+"Ponovno pokreni sustav kada je aplikacija zatražila zaustavljanje ponovnog "
+"pokretanja"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
+msgid ""
+"Authentication is required for rebooting the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Potrebna je ovjera za ponovno pokretanje sustava kada je aplikacija "
+"zatražila zaustavljanje ponovnog pokretanja."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
+msgid "Suspend the system"
+msgstr "Suspendiraj sustav"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
+msgid "Authentication is required for suspending the system."
+msgstr "Potrebna je ovjera za suspendiranje sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Suspend the system while other users are logged in"
+msgstr "Suspendiraj sustav kada su drugi korisnici prijavljeni"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid ""
+"Authentication is required for suspending the system while other users are "
+"logged in."
+msgstr ""
+"Potrebna je ovjera za suspendiranje sustava kada su drugi korisnici "
+"prijavljeni."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Suspend the system while an application asked to inhibit it"
+msgstr ""
+"Suspendiraj sustav kada je aplikacija zatražila zaustavljanje suspendiranja"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for suspending the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Potrebna je ovjera za suspendiranje sustava kada je aplikacija zatražila "
+"zaustavljanje suspendiranja."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Hibernate the system"
+msgstr "Hiberniraj sustav"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid "Authentication is required for hibernating the system."
+msgstr "Potrebna je ovjera za hibernaciju sustava."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
+msgid "Hibernate the system while other users are logged in"
+msgstr "Hiberniraj sustav kada su ostali korisnici prijavljeni."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
+msgid ""
+"Authentication is required for hibernating the system while other users are "
+"logged in."
+msgstr ""
+"Potrebna je ovjera za hibernaciju sustava kada su drugi korisnici "
+"prijavljeni."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
+msgid "Hibernate the system while an application asked to inhibit it"
+msgstr ""
+"Hiberniraj sustav kada je aplikacija zatražila zaustavljanje hibernacije"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid ""
+"Authentication is required for hibernating the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Potrebna je ovjera za hibernaciju sustava kada je aplikacija zatražila "
+"zaustavljanje hibernacije."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
+msgid "Manage active sessions, users and seats"
+msgstr ""
+"Upravljanje aktivnim sesijama, korisnicima i skupovima sesija i hardvera"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
+msgid ""
+"Authentication is required for managing active sessions, users and seats."
+msgstr ""
+"Potrebna je ovjera za upravljanje aktivnim sesijama, korisnicima i skupovima "
+"sesija i hardvera."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
+msgid "Lock or unlock active sessions"
+msgstr "Zaključavanje ili otključavanje aktivne sesije"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
+msgid "Authentication is required to lock or unlock active sessions."
+msgstr "Potrebna je ovjera za zaključavanje ili otključavanje aktivne sesije."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
+msgid "Allow indication to the firmware to boot to setup interface"
+msgstr "Dopusti najavu frimveru za pokretanje sučelja postavljanja"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid ""
+"Authentication is required to indicate to the firmware to boot to setup "
+"interface."
+msgstr "Potrebna je ovjera najave frimvera za pokretanje sučelja postavljanja."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Postavljanje zaslonske pruke"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "Potrebna je ovjera za postavljanje zaslonske pruke."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+msgid "Log into a local container"
+msgstr "Prijavi se u lokalni spremnik"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+msgid "Authentication is required to log into a local container."
+msgstr "Potrebna je ovjera za prijavu u lokalni spremnik."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Prijava na lokalno računalo"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "Potrebna je ovjera za prijavu na lokalno račuanlo."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Pokretanje ljuske u lokalnom spremniku"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Potrebna je ovjera za pokretanje ljuske u lokalnom spremniku."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Pokretanje ljuske na lokalnom računalu"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Potrebna je ovjera za pokretanje ljuske na lokalnom računalu."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Pokretanje pseudo TTY na lokalnom spremniku"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "Potrebna je ovjera za pokretanje pseudo TTY na lokalnom spremniku."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Pokretanje pseudo TTY na lokalnom računalu"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Potrebna je ovjera za pokretanje pseudo TTY na lokalnom računalu."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "Upravljanje lokalnim vurtualnim strojevima i spremnicima"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+msgid ""
+"Authentication is required to manage local virtual machines and containers."
+msgstr ""
+"Potrebna je ovjera za upravljanje lokalnim vurtualnim strojevima i "
+"spremnicima."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+msgid "Manage local virtual machine and container images"
+msgstr "Upravljanje lokalnim vurtualnim strojevima i spremnicima slika"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+msgid ""
+"Authentication is required to manage local virtual machine and container "
+"images."
+msgstr ""
+"Potrebna je ovjera za upravljanje lokalnim vurtualnim strojevima i "
+"spremnicima slika."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+msgid "Set system time"
+msgstr "Postavi vrijeme sustava"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+msgid "Authentication is required to set the system time."
+msgstr "Potrebna je ovjera za postavljanje vremena sustava."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+msgid "Set system timezone"
+msgstr "Postavi vremensku zonu sustava"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+msgid "Authentication is required to set the system timezone."
+msgstr "Potrebna je ovjera za postavljanje vremenske zone sustava."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+msgid "Set RTC to local timezone or UTC"
+msgstr "Postavi RTC u lokalnu vremensku zonu ili UTC"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+msgid ""
+"Authentication is required to control whether the RTC stores the local or "
+"UTC time."
+msgstr ""
+"Potrebna je ovjera za postavljanje RTC-a u lokalnu vremensku zonu ili UTC."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+msgid "Turn network time synchronization on or off"
+msgstr "Uključi ili isključi mrežno uklađivanje vremena"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+msgid ""
+"Authentication is required to control whether network time synchronization "
+"shall be enabled."
+msgstr ""
+"Potrebna je ovjera za uključivanje ili isključivanje mrežnog usklađivanja "
+"vremena."
+
+#: ../src/core/dbus-unit.c:428
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Potrebna je ovjera za pokretanje '$(unit)'."
+
+#: ../src/core/dbus-unit.c:429
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Potrebna je ovjera za zaustavljanje '$(unit)'."
+
+#: ../src/core/dbus-unit.c:430
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Potrebna je ovjera za ponovno učitavnje '$(unit)'."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Potrebna je ovjera za ponovno pokretanje'$(unit)'."
+
+#: ../src/core/dbus-unit.c:535
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Potrebna je ovjera za ubijanje '$(unit)'."
+
+#: ../src/core/dbus-unit.c:565
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Potrebna je ovjera za vraćanje \"neuspjelog\" stanja '$(unit)'."
+
+#: ../src/core/dbus-unit.c:597
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Potrebna je ovjera za postavljanje svojstava na '$(unit)'."
index c5dee25052039b928b00572b82af3d74e0df4a16..88fecbc506a30c48caf033fd81729e6f081c78cd 100644 (file)
--- a/po/hu.po
+++ b/po/hu.po
@@ -1,14 +1,14 @@
 # Hungarian translation of systemd
-# Copyright (C) 2015. Free Software Foundation, Inc.
+# Copyright (C) 2015, 2016. Free Software Foundation, Inc.
 # This file is distributed under the same license as the systemd package.
 #
-# Gabor Kelemen <kelemeng at gnome dot hu>, 2015.
+# Gabor Kelemen <kelemeng at gnome dot hu>, 2015, 2016.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-01-02 22:58+0100\n"
+"POT-Creation-Date: 2016-01-02 13:41+0100\n"
+"PO-Revision-Date: 2016-01-02 13:45+0100\n"
 "Last-Translator: Gabor Kelemen <kelemeng at ubuntu dot com>\n"
 "Language-Team: Hungarian <openscope at googlegroups dot com>\n"
 "Language: hu\n"
@@ -29,15 +29,13 @@ msgstr ""
 "Hitelesítés szükséges a bevitt jelmondat visszaküldéséhez a rendszernek."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
-#, fuzzy
 msgid "Manage system services or other units"
-msgstr "Rendszerszolgáltatások vagy -egységek kezelése"
+msgstr "Rendszerszolgáltatások vagy más egységek kezelése"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
 msgid "Authentication is required to manage system services or other units."
 msgstr ""
-"Hitelesítés szükséges a rendszerszolgáltatások vagy -egységek kezeléséhez."
+"Hitelesítés szükséges a rendszerszolgáltatások vagy más egységek kezeléséhez."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
 msgid "Manage system service or unit files"
@@ -51,14 +49,16 @@ msgstr ""
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
 msgid "Set or unset system and service manager environment variables"
 msgstr ""
+"Rendszer- és szolgáltatáskezelő környezeti változóinak beállítása vagy "
+"törlése"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
-#, fuzzy
 msgid ""
 "Authentication is required to set or unset system and service manager "
 "environment variables."
 msgstr ""
-"Hitelesítés szükséges a rendszerszolgáltatás- vagy egységfájlok kezeléséhez."
+"Hitelesítés szükséges a rendszer- és szolgáltatáskezelő környezeti "
+"változóinak beállításához vagy törléséhez."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
 msgid "Reload the systemd state"
@@ -98,30 +98,27 @@ msgstr "Hitelesítés szükséges a helyi gép információinak beállításáho
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:1
 msgid "Import a VM or container image"
-msgstr ""
+msgstr "VM vagy konténer lemezkép importálása"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to import a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához."
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:3
 msgid "Export a VM or container image"
-msgstr ""
+msgstr "VM vagy konténer lemezkép exportálása"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:4
-#, fuzzy
 msgid "Authentication is required to export a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép exportálásához."
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:5
 msgid "Download a VM or container image"
-msgstr ""
+msgstr "VM vagy konténer lemezkép letöltése"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:6
-#, fuzzy
 msgid "Authentication is required to download a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez."
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
 msgid "Set system locale"
@@ -409,65 +406,113 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Manage active sessions, users and seats"
-msgstr ""
+msgstr "Aktív munkamenetek, felhasználók és munkaállomások kezelése"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:50
-#, fuzzy
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
-"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy "
-"munkaállomáshoz"
+"Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások "
+"kezeléséhez."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Lock or unlock active sessions"
-msgstr ""
+msgstr "Aktív munkamenetek zárolása vagy feloldása"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:52
-#, fuzzy
 msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr ""
+"Hitelesítés szükséges az aktív munkamenetek zárolásához vagy feloldásához."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
+msgstr "A firmware-nek jelezhető, hogy a beállítófelületet bootolja"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:54
-#, fuzzy
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
-msgstr "Hitelesítés szükséges a helyi gépnév beállításához."
+msgstr ""
+"Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet "
+"bootolja"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Falüzenet beállítása"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "Hitelesítés szükséges a falüzenet beállításához"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Bejelentkezés helyi konténerbe"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to log into a local container."
 msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Manage local virtual machines and containers"
-msgstr ""
+msgid "Log into the local host"
+msgstr "Bejelentkezés a helyi gépre"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
-#, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Parancsértelmező elérése helyi konténerben"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez helyi konténerben."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Parancsértelmező elérése a helyi gépen"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez a helyi gépen."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Pszeudoterminál elérése helyi konténerben"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez helyi konténerben."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Pszeudoterminál elérése helyi gépen"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez a helyi gépen."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "Virtuális gépek és konténerek kezelése"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
-msgstr "Hitelesítés szükséges a helyi gép információinak beállításához."
+msgstr "Hitelesítés szükséges helyi virtuális gépek és konténerek kezeléséhez."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
-msgstr ""
+msgstr "Helyi virtuális gép és konténer lemezképek kezelése"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-#, fuzzy
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
-msgstr "Hitelesítés szükséges a helyi gép információinak beállításához."
+msgstr ""
+"Hitelesítés szükséges a helyi virtuális gép és konténer lemezképek "
+"kezeléséhez."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
 msgid "Set system time"
@@ -506,3 +551,34 @@ msgid ""
 "Authentication is required to control whether network time synchronization "
 "shall be enabled."
 msgstr "Hitelesítés szükséges a hálózati időszinkronizáció engedélyezéséhez."
+
+#: ../src/core/dbus-unit.c:449
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Hitelesítés szükséges a következő elindításához: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:450
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:451
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Hitelesítés szükséges a következő újraindításához: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:556
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Hitelesítés szükséges a következő kilövéséhez: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:586
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: "
+"„$(unit)”."
+
+#: ../src/core/dbus-unit.c:618
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr ""
+"Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”."
diff --git a/po/id.po b/po/id.po
new file mode 100755 (executable)
index 0000000..72eb94c
--- /dev/null
+++ b/po/id.po
@@ -0,0 +1,576 @@
+# Indonesian translation for systemd.
+# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
+# This file is distributed under the same license as the systemd package.
+# Andika Triwidada <andika@gmail.com>, 2014.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: systemd master\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2016-04-23 02:33+0000\n"
+"PO-Revision-Date: 2016-06-28 13:18+0700\n"
+"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
+"Language-Team: Indonesian <gnome-l10n-id@googlegroups.com>\n"
+"Language: id\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.8\n"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+msgid "Send passphrase back to system"
+msgstr "Kirim frasa sandi kembali ke sistem"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+msgid ""
+"Authentication is required to send the entered passphrase back to the system."
+msgstr ""
+"Otentikasi diperlukan untuk mengirim frasa sandi yang dimasukkan kembali ke "
+"sistem."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+msgid "Manage system services or other units"
+msgstr "Kelola layanan sistem atau unit lainnya"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+msgid "Authentication is required to manage system services or other units."
+msgstr ""
+"Otentikasi diperlukan untuk mengelola layanan sistem atau unit lainnya."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+msgid "Manage system service or unit files"
+msgstr "Kelola layanan sistem atau berkas unit"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+msgid "Authentication is required to manage system service or unit files."
+msgstr "Otentikasi diperlukan untuk mengelola layanan sistem atau berkas unit."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+msgid "Set or unset system and service manager environment variables"
+msgstr "Atur atau hapus variabel lingkungan manajer layanan dan sistem"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+msgid ""
+"Authentication is required to set or unset system and service manager "
+"environment variables."
+msgstr ""
+"Otentikasi diperlukan untuk menata atau menghapus variabel lingkungan "
+"manajer layanan dan sistem."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+msgid "Reload the systemd state"
+msgstr "Muat ulang keadaan systemd"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+msgid "Authentication is required to reload the systemd state."
+msgstr "Otentikasi diperlukan untuk memuat ulang keadaan systemd."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+msgid "Set host name"
+msgstr "Setel nama host"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+msgid "Authentication is required to set the local host name."
+msgstr "Otentikasi diperlukan untuk menata nama host lokal."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+msgid "Set static host name"
+msgstr "Setel nama host statik"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+msgid ""
+"Authentication is required to set the statically configured local host name, "
+"as well as the pretty host name."
+msgstr ""
+"Otentikasi diperlukan untuk menata nama host lokal yang dikonfigurasi "
+"statik, maupun nama host cantik."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+msgid "Set machine information"
+msgstr "Setel informasi mesin"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+msgid "Authentication is required to set local machine information."
+msgstr "Otentikasi diperlukan untuk menata informasi mesin lokal."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:1
+msgid "Import a VM or container image"
+msgstr "Impor sebuah image kontainer atau VM"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:2
+msgid "Authentication is required to import a VM or container image"
+msgstr "Otentikasi diperlukan untuk mengimpor suatu image kontainer atau VM"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:3
+msgid "Export a VM or container image"
+msgstr "Ekspor sebuah image kontainer atau VM"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:4
+msgid "Authentication is required to export a VM or container image"
+msgstr "Otentikasi diperlukan untuk mengekspor suatu image kontainer atau VM"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:5
+msgid "Download a VM or container image"
+msgstr "Unduh sebuah image kontainer atau VM"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:6
+msgid "Authentication is required to download a VM or container image"
+msgstr "Otentikasi diperlukan untuk mengunduh suatu image kontainer atau VM"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+msgid "Set system locale"
+msgstr "Setel locale sistem"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+msgid "Authentication is required to set the system locale."
+msgstr "Otentikasi diperlukan untuk menyetel locale sistem."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+msgid "Set system keyboard settings"
+msgstr "Setel pengaturan papan tik sistem"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+msgid "Authentication is required to set the system keyboard settings."
+msgstr "Otentikasi diperlukan untuk menyetel pengaturan papan tik sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:1
+msgid "Allow applications to inhibit system shutdown"
+msgstr "Ijinkan aplikasi untuk mencegah shutdown sistem"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:2
+msgid ""
+"Authentication is required for an application to inhibit system shutdown."
+msgstr ""
+"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah shutdown sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:3
+msgid "Allow applications to delay system shutdown"
+msgstr "Ijinkan aplikasi untuk menunda shutdown sistem"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:4
+msgid "Authentication is required for an application to delay system shutdown."
+msgstr ""
+"Otentikasi diperlukan bagi suatu aplikasi untuk menunda shutdown sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:5
+msgid "Allow applications to inhibit system sleep"
+msgstr "Ijinkan aplikasi untuk mencegah tidur sistem"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:6
+msgid "Authentication is required for an application to inhibit system sleep."
+msgstr "Otentikasi diperlukan bagi suatu aplikasi untuk menunda tidur sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:7
+msgid "Allow applications to delay system sleep"
+msgstr "Ijinkan aplikasi untuk menunda tidur sistem"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:8
+msgid "Authentication is required for an application to delay system sleep."
+msgstr "Otentikasi diperlukan bagi suatu aplikasi untuk menunda tidur sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:9
+msgid "Allow applications to inhibit automatic system suspend"
+msgstr "Ijinkan aplikasi mencegah suspensi sistem otomatis"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:10
+msgid ""
+"Authentication is required for an application to inhibit automatic system "
+"suspend."
+msgstr ""
+"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah suspensi sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:11
+msgid "Allow applications to inhibit system handling of the power key"
+msgstr "Ijinkan aplikasi mencegah penanganan sistem atas tombol daya"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:12
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the power key."
+msgstr ""
+"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah penanganan sistem "
+"atas tombol daya."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:13
+msgid "Allow applications to inhibit system handling of the suspend key"
+msgstr "Ijinkan aplikasi mencegah penanganan sistem atas tombol suspensi"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:14
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the suspend key."
+msgstr ""
+"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah penanganan sistem "
+"atas tombol suspensi."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:15
+msgid "Allow applications to inhibit system handling of the hibernate key"
+msgstr "Ijinkan aplikasi mencegah penanganan sistem atas tombol hibernasi"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:16
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the hibernate key."
+msgstr ""
+"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah penanganan sistem "
+"dari tombol hibernasi."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:17
+msgid "Allow applications to inhibit system handling of the lid switch"
+msgstr "Ijinkan aplikasi mencegah penanganan sistem atas saklar lid"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:18
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the lid switch."
+msgstr ""
+"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah penanganan sistem "
+"atas saklar lid."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr "Ijinkan pengguna yang tidak log masuk menjalankan program"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Permintaan eksplisit diperlukan untuk menjalankan program sebagai pengguna "
+"yang tidak log masuk."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow non-logged-in users to run programs"
+msgstr "Ijinkan pengguna yang tidak log masuk menjalankan program"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
+msgid "Authentication is required to run programs as a non-logged-in user."
+msgstr ""
+"Otentikasi diperlukan untuk menjalankan program sebagai pengguna yang tidak "
+"log masuk."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
+msgid "Allow attaching devices to seats"
+msgstr "Ijinkan mencantolkan perangkat ke seat"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
+msgid "Authentication is required for attaching a device to a seat."
+msgstr "Otentikasi diperlukan untuk mencantol suatu perangkat ke sebuah seat."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
+msgid "Flush device to seat attachments"
+msgstr "Siram perangkat untuk mendudukkan lampiran"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
+msgid ""
+"Authentication is required for resetting how devices are attached to seats."
+msgstr ""
+"Otentikasi diperlukan untuk me-reset bagaimana perangkat dicantolkan ke seat."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
+msgid "Power off the system"
+msgstr "Matikan daya sistem"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
+msgid "Authentication is required for powering off the system."
+msgstr "Otentikasi diperlukan untuk mematikan daya sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
+msgid "Power off the system while other users are logged in"
+msgstr "Matikan daya sistem ketika pengguna lain sedang log masuk"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
+msgid ""
+"Authentication is required for powering off the system while other users are "
+"logged in."
+msgstr ""
+"Otentikasi diperlukan untuk mematikan daya sistem ketika pengguna lain "
+"sedang log masuk."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
+msgid "Power off the system while an application asked to inhibit it"
+msgstr "Matikan daya sistem ketika sebuah aplikasi meminta untuk mencegahnya"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
+msgid ""
+"Authentication is required for powering off the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Otentikasi diperlukan untuk mematikan daya sistem ketika sebuah aplikasi "
+"meminta untuk mencegahnya."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
+msgid "Reboot the system"
+msgstr "Boot ulang sistem"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
+msgid "Authentication is required for rebooting the system."
+msgstr "Otentikasi diperlukan untuk mem-boot ulang sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
+msgid "Reboot the system while other users are logged in"
+msgstr "Boot ulang sistem ketika pengguna lain sedang log masuk"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
+msgid ""
+"Authentication is required for rebooting the system while other users are "
+"logged in."
+msgstr ""
+"Otentikasi diperlukan untuk mem-boot ulang sistem ketika pengguna lain "
+"sedang log masuk."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
+msgid "Reboot the system while an application asked to inhibit it"
+msgstr "Boot ulang sistem ketika sebuah aplikasi meminta untuk mencegahnya"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
+msgid ""
+"Authentication is required for rebooting the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Otentikasi diperlukan untuk mem-boot ulang sistem ketika sebuah aplikasi "
+"meminta untuk mencegahnya."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Suspend the system"
+msgstr "Suspensikan sistem"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid "Authentication is required for suspending the system."
+msgstr "Otentikasi diperlukan untuk mensuspensi sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Suspend the system while other users are logged in"
+msgstr "Suspensikan sistem ketika pengguna lain sedang log masuk"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for suspending the system while other users are "
+"logged in."
+msgstr ""
+"Otentikasi diperlukan untuk mensuspensi sistem ketika pengguna lain sedang "
+"log masuk."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Suspend the system while an application asked to inhibit it"
+msgstr "Suspensikan sistem ketika sebuah aplikasi meminta untuk mencegahnya"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid ""
+"Authentication is required for suspending the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Otentikasi diperlukan untuk mensuspensi sistem ketika suatu aplikasi meminta "
+"untuk mencegahnya."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
+msgid "Hibernate the system"
+msgstr "Hibernasikan sistem"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
+msgid "Authentication is required for hibernating the system."
+msgstr "Otentikasi diperlukan untuk menghibernasi sistem."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
+msgid "Hibernate the system while other users are logged in"
+msgstr "Hibernasikan sistem ketika pengguna lain sedang log masuk."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid ""
+"Authentication is required for hibernating the system while other users are "
+"logged in."
+msgstr ""
+"Otentikasi diperlukan untuk menghibernasi sistem ketika pengguna lain sedang "
+"log masuk."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
+msgid "Hibernate the system while an application asked to inhibit it"
+msgstr "Hibernasikan sistem ketika sebuah aplikasi meminta untuk mencegahnya."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
+msgid ""
+"Authentication is required for hibernating the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Otentikasi diperlukan untuk menghibernasi sistem ketika sebuah aplikasi "
+"meminta mencegahnya."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
+msgid "Manage active sessions, users and seats"
+msgstr "Kelola seat, pengguna, dan sesi aktif"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
+msgid ""
+"Authentication is required for managing active sessions, users and seats."
+msgstr "Otentikasi diperlukan untuk mengelola seat, pengguna, dan sesi aktif."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
+msgid "Lock or unlock active sessions"
+msgstr "Kunci/buka kunci sesi aktif"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid "Authentication is required to lock or unlock active sessions."
+msgstr "Otentikasi diperlukan untuk mengunci atau membuka kunci sesi aktif."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Allow indication to the firmware to boot to setup interface"
+msgstr "Ijinkan indikasi ke firmware untuk boot ke antar muka penyiapan"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid ""
+"Authentication is required to indicate to the firmware to boot to setup "
+"interface."
+msgstr ""
+"Otentikasi diperlukan untuk mengindikasikan ke firmware agar boot ke "
+"antarmuka penyiapan."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
+msgid "Set a wall message"
+msgstr "Setel suatu pesan wall"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
+msgid "Authentication is required to set a wall message"
+msgstr "Otentikasi diperlukan untuk menyetel pesan wall"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+msgid "Log into a local container"
+msgstr "Log masuk ke dalam suatu kontainer lokal"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+msgid "Authentication is required to log into a local container."
+msgstr "Otentikasi diperlukan untuk log masuk ke dalam suatu kontainer lokal."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Log masuk ke dalam host lokal"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "Otentikasi diperlukan untuk log masuk ke dalam host lokal."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Dapatkan sebuah shell dalam kontainer lokal"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr ""
+"Otentikasi diperlukan untuk mendapatkan suatu shell dalam sebuah kontainer "
+"lokal."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Dapatkan sebuah shell pada host lokal"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Otentikasi diperlukan untuk mendapatkan suatu shell pada host lokal."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Dapatkan sebuah TTY semu dalam suatu kontainer lokal"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+"Otentikasi diperlukan untuk mendapatkan suatu TTY semu dalam sebuah "
+"kontainer lokal."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Dapatkan sebuah TTY semu pada host lokal"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr ""
+"Otentikasi diperlukan untuk mendapatkan suatu TTY semu pada host lokal."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "Kelola mesin virtual lokal dan kontainer"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+msgid ""
+"Authentication is required to manage local virtual machines and containers."
+msgstr ""
+"Otentikasi diperlukan untuk mengelola mesin virtual lokal dan kontainer."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+msgid "Manage local virtual machine and container images"
+msgstr "Kelola mesin virtual lokal dan image kontainer"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+msgid ""
+"Authentication is required to manage local virtual machine and container "
+"images."
+msgstr ""
+"Otentikasi diperlukan untuk mengelola mesin virtual lokal dan image "
+"kontainer."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+msgid "Set system time"
+msgstr "Setel waktu sistem"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+msgid "Authentication is required to set the system time."
+msgstr "Otentikasi diperlukan untuk menyetel waktu sistem."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+msgid "Set system timezone"
+msgstr "Setel zona waktu sistem"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+msgid "Authentication is required to set the system timezone."
+msgstr "Otentikasi diperlukan untuk menyetel zona waktu sistem."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+msgid "Set RTC to local timezone or UTC"
+msgstr "Atur RTC ke zona waktu lokal atau UTC"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+msgid ""
+"Authentication is required to control whether the RTC stores the local or "
+"UTC time."
+msgstr ""
+"Otentikasi diperlukan untuk mengendalikan apakah RTC menyimpan waktu UTC "
+"atau lokal."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+msgid "Turn network time synchronization on or off"
+msgstr "Nyalakan atau matikan penyelarasan waktu jaringan"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+msgid ""
+"Authentication is required to control whether network time synchronization "
+"shall be enabled."
+msgstr ""
+"Otentikasi diperlukan untuk mengendalikan apakah sinkronisasi waktu jaringan "
+"mesti difungsikan."
+
+#: ../src/core/dbus-unit.c:450
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Otentikasi diperlukan untuk memulai '$(unit)'."
+
+#: ../src/core/dbus-unit.c:451
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Otentikasi diperlukan untuk menghentikan '$(unit)'."
+
+#: ../src/core/dbus-unit.c:452
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Otentikasi diperlukan untuk memuat ulang '$(unit)'."
+
+#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Otentikasi diperlukan untuk memulai ulang '$(unit)'."
+
+#: ../src/core/dbus-unit.c:560
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Otentikasi diperlukan untuk mematikan '$(unit)'."
+
+#: ../src/core/dbus-unit.c:590
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Otentikasi diperlukan untuk me-reset keadaan \"failed\" dari '$(unit)'."
+
+#: ../src/core/dbus-unit.c:622
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Otentikasi diperlukan untuk menata properti pada '$(unit)'."
index e11e7e3faadbb1494e8061c855aef93f88a7ba8c..7afa5c3b9cc4ea36cbd7fccb633a302bb1438a14 100644 (file)
--- a/po/it.po
+++ b/po/it.po
@@ -1,14 +1,14 @@
 # Italian translations for systemd package
 # Traduzione in italiano per il pacchetto systemd
 # This file is distributed under the same license as the systemd package.
-# Daniele Medri <dmedri@gmail.com>, 2013-2015.
+# Daniele Medri <dmedri@gmail.com>, 2013-2016.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-06-10 23:10+0100\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2016-07-15 13:11+0200\n"
+"PO-Revision-Date: 2016-07-20 10:54+0200\n"
 "Last-Translator: Daniele Medri <dmedri@gmail.com>\n"
 "Language-Team: Italian\n"
 "Language: it\n"
@@ -16,11 +16,11 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 1.7.6\n"
+"X-Generator: Poedit 1.8.7.1\n"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
 msgid "Send passphrase back to system"
-msgstr "Inviare la frase segreta (passphrase) al sistema"
+msgstr "Invia la frase segreta (passphrase) al sistema"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
 msgid ""
@@ -63,7 +63,7 @@ msgstr ""
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
 msgid "Reload the systemd state"
-msgstr "Riavviare lo stato di systemd"
+msgstr "Ricarica lo stato di systemd"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
 msgid "Authentication is required to reload the systemd state."
@@ -251,48 +251,58 @@ msgstr ""
 "gestione di sistema alla apertura/chiusura del portatile."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
-msgid "Allow non-logged-in users to run programs"
+msgid "Allow non-logged-in user to run programs"
 msgstr "Consenti agli utenti non connessi di eseguire programmi"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"E' necessaria un'esplicita richiesta per eseguire programmi come utenti non "
+"connessi."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow non-logged-in users to run programs"
+msgstr "Consenti agli utenti non connessi di eseguire programmi"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
 "Autenticazione richiesta per consentire agli utenti non connessi di eseguire "
 "programmi."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
 msgstr "Consenti di collegare dispositivi alle postazioni"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
 msgstr ""
 "Autenticazione richiesta per collegare un dispositivo ad una postazione."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
 msgstr "Scollega i dispositivi dalla postazione"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr ""
 "Autenticazione richiesta per ripristinare come i dispositivi sono collegati "
 "alle postazioni."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
-msgstr "Spegnere il sistema"
+msgstr "Spegni il sistema"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
 msgstr "Autenticazione richiesta per spegnere il sistema."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
-msgstr "Spegnere il sistema mentre altri utenti sono connessi"
+msgstr "Spegni il sistema mentre altri utenti sono connessi"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
@@ -300,11 +310,11 @@ msgstr ""
 "Autenticazione richiesta per spegnere il sistema mentre altri utenti sono "
 "connessi."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
-msgstr "Spegnere il sistema mentre un'applicazione chiede di inibirne l'azione"
+msgstr "Spegni il sistema mentre un'applicazione chiede di inibirne l'azione"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
@@ -312,19 +322,19 @@ msgstr ""
 "Autenticazione richiesta per spegnere il sistema mentre un'applicazione "
 "chiede di inibirne l'azione."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
-msgstr "Riavviare il sistema"
+msgstr "Riavvia il sistema"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
 msgstr "Autenticazione richiesta per riavviare il sistema."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
-msgstr "Riavviare il sistema mentre altri utenti sono connessi"
+msgstr "Riavvia il sistema mentre altri utenti sono connessi"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
@@ -332,12 +342,11 @@ msgstr ""
 "Autenticazione richiesta per riavviare il sistema mentre altri utenti sono "
 "connessi."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
-msgstr ""
-"Riavviare il sistema mentre un'applicazione chiede di inibirne l'azione"
+msgstr "Riavvia il sistema mentre un'applicazione chiede di inibirne l'azione"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
@@ -345,19 +354,19 @@ msgstr ""
 "Autenticazione richiesta per riavviare il sistema mentre un'applicazione "
 "chiede di inibirne l'azione."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
-msgstr "Sospendere il sistema"
+msgstr "Sospendi il sistema"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
 msgstr "Autenticazione richiesta per sospendere il sistema."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
-msgstr "Sospendere il sistema mentre altri utenti sono connessi"
+msgstr "Sospendi il sistema mentre altri utenti sono connessi"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
@@ -365,12 +374,11 @@ msgstr ""
 "Autenticazione richiesta per sospendere il sistema mentre altri utenti sono "
 "connessi."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
-msgstr ""
-"Sospendere il sistema mentre un'applicazione chiede di inibirne l'azione"
+msgstr "Sospendi il sistema mentre un'applicazione chiede di inibirne l'azione"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
@@ -378,19 +386,19 @@ msgstr ""
 "Autenticazione richiesta per sospendere il sistema mentre un'applicazione "
 "chiede di inibirne l'azione."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
-msgstr "Ibernare il sistema"
+msgstr "Iberna il sistema"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
 msgstr "Autenticazione richiesta per ibernare il sistema."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
-msgstr "Ibernare il sistema mentre altri utenti sono connessi"
+msgstr "Iberna il sistema mentre altri utenti sono connessi"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
@@ -398,11 +406,11 @@ msgstr ""
 "Autenticazione richiesta per ibernare il sistema mentre altri utenti sono "
 "connessi."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
-msgstr "Ibernare il sistema mentre un'applicazione chiede di inibirne l'azione"
+msgstr "Iberna il sistema mentre un'applicazione chiede di inibirne l'azione"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
@@ -410,32 +418,31 @@ msgstr ""
 "Autenticazione richiesta per ibernare il sistema mentre un'applicazione "
 "chiede di inibirne l'azione."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
 msgstr "Gestione delle sessioni attive, utenti e postazioni"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
 "Autenticazione richiesta per gestire le sessioni attive, gli utenti e le "
 "postazioni."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
 msgstr "Blocca/sblocca sessioni attive"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
 msgstr "Autenticazione richiesta per bloccare o sbloccare le sessioni attive."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
 msgstr ""
-"Permette indicazioni per il firmware per avviare l'interfaccia di "
-"configurazione"
+"Permette indicazioni al firmware per avviare l'interfaccia di configurazione"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
@@ -443,6 +450,14 @@ msgstr ""
 "Autenticazione richiesta per indicare al firmware di avviare l'interfaccia "
 "di configurazione."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
+msgid "Set a wall message"
+msgstr "Configura un messaggio per gli utenti"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
+msgid "Authentication is required to set a wall message"
+msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Accedi in un container locale"
@@ -452,20 +467,62 @@ msgid "Authentication is required to log into a local container."
 msgstr "Autenticazione richiesta per accedere in un container locale."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Accedi in un host locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "Autenticazione richiesta per accedere in un host locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Apri una shell in un container locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Autenticazione richiesta per aprire una shell in un container locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Apri una shell in un host locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Autenticazione richiesta per aprire una shell in un host locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Apri un pseudo TTY in un container locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+"Autenticazione richiesta per aprire un pseudo TTY in un container locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Apri un pseudo TTY in un host locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Autenticazione richiesta per aprire un pseudo TTY in un host locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
 msgstr "Gestisci le virtual machine e i container locali"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr ""
 "Autenticazione richiesta per gestire le virtual machine e i container locali."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
 msgstr "Gestisci le immagini locali delle virtual machine e dei container"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
@@ -514,3 +571,32 @@ msgid ""
 msgstr ""
 "Autenticazione richiesta per verificare se la sincronizzazione dell'orario "
 "in rete possa essere attivata."
+
+#: ../src/core/dbus-unit.c:450
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Autenticazione richiesta per avviare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:451
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Autenticazione richiesta per fermare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:452
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Autenticazione richiesta per ricaricare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Autenticazione richiesta per riavviare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:560
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Autenticazione richiesta per terminare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:590
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Autenticazione richiesta per riconfigurare lo stato \"fallito\" di '$(unit)'."
+
+#: ../src/core/dbus-unit.c:622
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Autenticazione richiesta per configurare le proprietà di '$(unit)'."
index d3e2ae8418d58582ff863f197cd2114c7e0dabfa..92e9a209cca4f576b243edeaf8c43ff14f5a99e0 100644 (file)
--- a/po/pl.po
+++ b/po/pl.po
@@ -1,13 +1,13 @@
 # translation of pl.po to Polish
-# Piotr Drąg <piotrdrag@gmail.com>, 2011, 2013, 2014, 2015.
+# Piotr Drąg <piotrdrag@gmail.com>, 2011, 2013, 2014, 2015, 2016.
 # Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>, 2011.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-06 20:39+0200\n"
-"PO-Revision-Date: 2015-09-06 20:40+0200\n"
+"POT-Creation-Date: 2016-04-23 14:24+0200\n"
+"PO-Revision-Date: 2016-04-23 14:25+0200\n"
 "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
 "Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
 "Language: pl\n"
@@ -241,48 +241,58 @@ msgstr ""
 "przez system."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr "Zezwolenie niezalogowanemu użytkownikowi na uruchamianie programów"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Wymagane jest bezpośrednie żądanie, aby uruchamiać programy jako "
+"niezalogowany użytkownik."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
 msgid "Allow non-logged-in users to run programs"
 msgstr "Zezwolenie niezalogowanym użytkownikom na uruchamianie programów"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby uruchamiać programy jako niezalogowany "
 "użytkownik."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
 msgstr "Zezwolenie na podłączanie urządzeń do stanowisk"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby podłączyć urządzenie do stanowiska."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
 msgstr "Usunięcie podłączenia urządzeń do stanowisk"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby ponownie ustawić sposób podłączenia "
 "urządzeń do stanowisk."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
 msgstr "Wyłączenie systemu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
 msgstr "Wymagane jest uwierzytelnienie, aby wyłączyć system."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
 msgstr "Wyłączenie systemu, kiedy są zalogowani inni użytkownicy"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
@@ -290,11 +300,11 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy są zalogowani "
 "inni użytkownicy."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
 msgstr "Wyłączenie systemu, kiedy program zażądał jego wstrzymania"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
@@ -302,19 +312,19 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy program zażądał "
 "jego wstrzymania."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
 msgstr "Ponowne uruchomienie systemu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
 msgstr "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
 msgstr "Ponowne uruchomienie systemu, kiedy są zalogowani inni użytkownicy"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
@@ -322,11 +332,11 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy są "
 "zalogowani inni użytkownicy."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
 msgstr "Ponowne uruchomienie systemu, kiedy program zażądał jego wstrzymania"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
@@ -334,19 +344,19 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy program "
 "zażądał jego wstrzymania."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
 msgstr "Uśpienie systemu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
 msgstr "Wymagane jest uwierzytelnienie, aby uśpić system."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
 msgstr "Uśpienie systemu, kiedy są zalogowani inni użytkownicy"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
@@ -354,11 +364,11 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby uśpić system, kiedy są zalogowani inni "
 "użytkownicy."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
 msgstr "Uśpienie systemu, kiedy program zażądał jego wstrzymania"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
@@ -366,19 +376,19 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby uśpić system, kiedy program zażądał jego "
 "wstrzymania."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
 msgstr "Hibernacja systemu"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
 msgstr "Wymagane jest uwierzytelnienie, aby zahibernować system."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
 msgstr "Hibernacja systemu, kiedy są zalogowani inni użytkownicy"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
@@ -386,11 +396,11 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy są zalogowani "
 "inni użytkownicy."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
 msgstr "Hibernacja systemu, kiedy program zażądał jej wstrzymania"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
@@ -398,31 +408,31 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy program "
 "zażądał jej wstrzymania."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
 msgstr "Zarządzanie aktywnymi sesjami, użytkownikami i stanowiskami"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby zarządzać aktywnymi sesjami, "
 "użytkownikami i stanowiskami."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
 msgstr "Zablokowanie lub odblokowanie aktywnych sesji"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby zablokować lub odblokować aktywne sesje."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
 msgstr "Wskazanie oprogramowaniu sprzętowemu, aby uruchomić interfejs ustawień"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
@@ -430,11 +440,11 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby wskazać oprogramowaniu sprzętowemu, że "
 "należy uruchomić interfejs ustawień."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
 msgid "Set a wall message"
 msgstr "Ustawienie komunikatu wall"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
 msgid "Authentication is required to set a wall message"
 msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
 
@@ -557,36 +567,36 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację "
 "czasu przez sieć."
 
-#: ../src/core/dbus-unit.c:428
+#: ../src/core/dbus-unit.c:450
 msgid "Authentication is required to start '$(unit)'."
 msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”."
 
-#: ../src/core/dbus-unit.c:429
+#: ../src/core/dbus-unit.c:451
 msgid "Authentication is required to stop '$(unit)'."
 msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”."
 
-#: ../src/core/dbus-unit.c:430
+#: ../src/core/dbus-unit.c:452
 msgid "Authentication is required to reload '$(unit)'."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”."
 
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
 msgid "Authentication is required to restart '$(unit)'."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”."
 
-#: ../src/core/dbus-unit.c:535
+#: ../src/core/dbus-unit.c:560
 msgid "Authentication is required to kill '$(unit)'."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby wymusić wyłączenie jednostki „$(unit)”."
 
-#: ../src/core/dbus-unit.c:565
+#: ../src/core/dbus-unit.c:590
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby przywrócić stan „failed” (niepowodzenia) "
 "jednostki „$(unit)”."
 
-#: ../src/core/dbus-unit.c:597
+#: ../src/core/dbus-unit.c:622
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby ustawić właściwości jednostki „$(unit)”."
index 1dd5900e2f7bd482f31cce03b165b06095819c97..2a11371f97924d3a2ffeecac714c2f8a7b9fb105 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
 "PO-Revision-Date: 2015-01-10 12:23-0300\n"
 "Last-Translator: Rafael Ferreira <rafael.f.f1@gmail.com>\n"
 "Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
@@ -441,6 +441,15 @@ msgid ""
 "interface."
 msgstr "É necessária autenticação para definir nome de máquina local."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#, fuzzy
+msgid "Authentication is required to set a wall message"
+msgstr "É necessária autenticação para definir nome de máquina local."
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Conectar a um contêiner local"
@@ -451,20 +460,69 @@ msgid "Authentication is required to log into a local container."
 msgstr "É necessária autenticação para se conectar a um contêiner local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#, fuzzy
+msgid "Log into the local host"
+msgstr "Conectar a um contêiner local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "É necessária autenticação para se conectar a um contêiner local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#, fuzzy
+msgid "Acquire a shell in a local container"
+msgstr "Conectar a um contêiner local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#, fuzzy
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "É necessária autenticação para se conectar a um contêiner local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+#, fuzzy
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "É necessária autenticação para definir nome de máquina local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#, fuzzy
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Conectar a um contêiner local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#, fuzzy
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "É necessária autenticação para se conectar a um contêiner local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+#, fuzzy
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "É necessária autenticação para definir nome de máquina local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
 msgstr ""
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 #, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr "É necessária autenticação para definir informações de máquina local."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
 msgstr ""
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 #, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machine and container "
@@ -510,3 +568,38 @@ msgid ""
 msgstr ""
 "É necessária autenticação para controlar se deve ser habilitada, ou não, a "
 "sincronização de horário através de rede."
+
+#: ../src/core/dbus-unit.c:428
+#, fuzzy
+msgid "Authentication is required to start '$(unit)'."
+msgstr "É necessária autenticação para definir o horário do sistema."
+
+#: ../src/core/dbus-unit.c:429
+#, fuzzy
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "É necessária autenticação para definir o horário do sistema."
+
+#: ../src/core/dbus-unit.c:430
+#, fuzzy
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "É necessária autenticação para recarregar o estado do sistema."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#, fuzzy
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "É necessária autenticação para definir o horário do sistema."
+
+#: ../src/core/dbus-unit.c:535
+#, fuzzy
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "É necessária autenticação para se conectar a um contêiner local."
+
+#: ../src/core/dbus-unit.c:565
+#, fuzzy
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "É necessária autenticação para definir nome de máquina local."
+
+#: ../src/core/dbus-unit.c:597
+#, fuzzy
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "É necessária autenticação para definir o horário do sistema."
index efb6f7b414d71a92cc9dfcdeca0df3ac0009e55a..0c0fab780e4b3cba82fff4f67c36750825d3faca 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -1,13 +1,13 @@
 # translation of ru.po to Rissian
 # Julia Dronova <juliette.tux@gmail.com>, 2013.
-# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2015.
+# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2016.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-03-22 21:53+0300\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
+"PO-Revision-Date: 2016-02-02 20:22+0300\n"
 "Last-Translator: Sergey Ptashnick <0comffdiz@inbox.ru>\n"
 "Language: ru\n"
 "MIME-Version: 1.0\n"
@@ -26,12 +26,10 @@ msgid ""
 msgstr "Чтобы отправить пароль системе, необходимо пройти аутентификацию."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
-#, fuzzy
 msgid "Manage system services or other units"
 msgstr "Управление системными службами и юнитами"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
 msgid "Authentication is required to manage system services or other units."
 msgstr ""
 "Для управления системными службами и юнитами, необходимо пройти "
@@ -456,14 +454,24 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
+msgstr "Разрешить загрузку в режиме настройки прошивки материнской платы"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:54
-#, fuzzy
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
-msgstr "Чтобы настроить имя компьютера, необходимо пройти аутентификацию."
+msgstr ""
+"Чтобы разрешить загрузку в режиме настройки прошивки материнской платы, "
+"необходимо пройти аутентификацию."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Отправить сообщение на все терминалы"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr ""
+"Чтобы отправить сообщение на все терминалы, необходимо пройти аутентификацию."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
@@ -474,21 +482,70 @@ msgid "Authentication is required to log into a local container."
 msgstr "Чтобы зайти в локальный контейнер, необходимо пройти аутентификацию."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Зайти на этот компьютер"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "Чтобы зайти на этот компьютер, необходимо пройти аутентификацию."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Получить командную оболочку в локальном контейнере"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr ""
+"Чтобы получить командную оболочку в локальном контейнере, необходимо пройти "
+"аутентификацию."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Запустить командную оболочку на этом компьютере"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr ""
+"Чтобы запустить командную оболочку на этом компьютере, необходимо пройти "
+"аутентификацию."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Получить псевдо-терминал в локальном контейнере"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+"Чтобы получить псевдо-терминал в локальном контейнере, необходимо пройти "
+"аутентификацию."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Получить псевдо-терминал на этом компьютере"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr ""
+"Чтобы получить псевдо-терминал на этом компьютере, необходимо пройти "
+"аутентификацию."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
 msgstr "Управление виртуальными машинами и контейнерами"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr ""
 "Для управления виртуальными машинами и контейнерами, необходимо пройти "
 "аутентификацию."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
 msgstr "Управление образами виртуальных машин и контейнеров"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
@@ -536,6 +593,39 @@ msgstr ""
 "Чтобы включить или выключить синхронизацию времени по сети, необходимо "
 "пройти аутентификацию."
 
+#: ../src/core/dbus-unit.c:428
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Чтобы запустить «$(unit)», необходимо пройти аутентификацию."
+
+#: ../src/core/dbus-unit.c:429
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Чтобы остановить «$(unit)», необходимо пройти аутентификацию."
+
+#: ../src/core/dbus-unit.c:430
+msgid "Authentication is required to reload '$(unit)'."
+msgstr ""
+"Чтобы заставить «$(unit)» перечитать конфигурацию, необходимо пройти "
+"аутентификацию."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Чтобы перезапустить «$(unit)», необходимо пройти аутентификацию."
+
+#: ../src/core/dbus-unit.c:535
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Чтобы убить юнит «$(unit)», необходимо пройти аутентификацию."
+
+#: ../src/core/dbus-unit.c:565
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Чтобы сбросить состояние «failed» у юнита «$(unit)», необходимо пройти "
+"аутентификацию."
+
+#: ../src/core/dbus-unit.c:597
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Чтобы изменить параметры юнита «$(unit)», необходимо пройти "
+"аутентификацию."
+
 #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
 #~ msgstr ""
 #~ "Чтобы прервать все запущенные проверки файловых систем, нажмите Ctrl+C"
index af8f421abbf831b346325ced8f1553059d089fb8..28307413096b44c1913bad8eba1fbf1529cf3aa8 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
 "PO-Revision-Date: 2015-03-14 11:09+0100\n"
 "Last-Translator: Sebastian Rasmussen <sebras@gmail.com>\n"
 "Language-Team: Swedish\n"
@@ -418,6 +418,15 @@ msgid ""
 "interface."
 msgstr "Autentisering krävs för att ange lokalt värdnamn."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#, fuzzy
+msgid "Authentication is required to set a wall message"
+msgstr "Autentisering krävs för att ange lokalt värdnamn."
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Logga till en lokal behållare"
@@ -427,20 +436,69 @@ msgid "Authentication is required to log into a local container."
 msgstr "Autentisering krävs för att logga till en lokal behållare"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#, fuzzy
+msgid "Log into the local host"
+msgstr "Logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "Autentisering krävs för att logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#, fuzzy
+msgid "Acquire a shell in a local container"
+msgstr "Logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#, fuzzy
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Autentisering krävs för att logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+#, fuzzy
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Autentisering krävs för att ange lokalt värdnamn."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#, fuzzy
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#, fuzzy
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "Autentisering krävs för att logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+#, fuzzy
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Autentisering krävs för att ange lokalt värdnamn."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
 msgstr "Hantera lokala virtuella maskiner och behållare"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr ""
 "Autentisering krävs för att hantera lokala virtuella maskiner och behållare."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
 msgstr "Hantera lokala virtuella maskin- och behållaravbildningar"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
@@ -490,6 +548,41 @@ msgstr ""
 "Autentisering krävs för att kontrollera huruvida synkronisering av "
 "nätverkstid ska vara aktiverat."
 
+#: ../src/core/dbus-unit.c:428
+#, fuzzy
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Autentisering krävs för ange systemtiden."
+
+#: ../src/core/dbus-unit.c:429
+#, fuzzy
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Autentisering krävs för ange systemtiden."
+
+#: ../src/core/dbus-unit.c:430
+#, fuzzy
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Autentisering krävs för att läsa om tillståndet för systemd."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#, fuzzy
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Autentisering krävs för ange systemtiden."
+
+#: ../src/core/dbus-unit.c:535
+#, fuzzy
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Autentisering krävs för att logga till en lokal behållare"
+
+#: ../src/core/dbus-unit.c:565
+#, fuzzy
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Autentisering krävs för att ange lokalt värdnamn."
+
+#: ../src/core/dbus-unit.c:597
+#, fuzzy
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Autentisering krävs för ange systemtiden."
+
 #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
 #~ msgstr "Tryck Ctrl+C för att avbryta alla pågående filsystemskontroller."
 
index 076627e4289ba786466604883e1c78c60f6d1e78..b71f30b835bcd9081d4bef36c75f145e2266a9e8 100644 (file)
--- a/po/tr.po
+++ b/po/tr.po
@@ -3,20 +3,20 @@
 # This file is distributed under the same license as the systemd package.
 # Necdet Yücel <necdetyucel@gmail.com>, 2014.
 # Gökhan Gurbetoğlu <ggurbet@gmail.com>, 2015.
-# Muhammet Kara <muhammetk@gmail.com>, 2015.
+# Muhammet Kara <muhammetk@gmail.com>, 2015, 2016.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2015-09-18 00:07+0000\n"
-"PO-Revision-Date: 2015-09-19 08:31+0300\n"
+"POT-Creation-Date: 2016-04-24 12:53+0000\n"
+"PO-Revision-Date: 2016-06-09 16:05+0300\n"
 "Last-Translator: Muhammet Kara <muhammetk@gmail.com>\n"
-"Language-Team: Türkçe <gnome-turk@gnome.org>\n"
+"Language-Team: Turkish <gnome-turk@gnome.org>\n"
+"Language: tr_TR\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Language: tr_TR\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 "X-Generator: Gtranslator 2.91.7\n"
 
@@ -249,48 +249,60 @@ msgstr ""
 "kimlik doğrulaması gereklidir."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
+#| msgid "Allow non-logged-in users to run programs"
+msgid "Allow non-logged-in user to run programs"
+msgstr "Oturum açmamış kullanıcının program çalıştırmasına izin ver"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#| msgid "Authentication is required to run programs as a non-logged-in user."
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Oturum açmamış bir kullanıcı olarak program çalıştırmak için açıkça istekte "
+"bulunulması gerekir."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
 msgid "Allow non-logged-in users to run programs"
 msgstr "Oturum açmamış kullanıcıların program çalıştırmasına izin ver"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
 "Oturum açmamış bir kullanıcı olarak program çalıştırmak için kimlik "
 "doğrulaması gereklidir."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
 msgstr "Aygıtların yuvaya takılmasına izin ver"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
 msgstr ""
 "Bir aygıtın yuvaya takılmasına izin vermek kimlik doğrulaması gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
 msgstr "Aygıtın yuvaya eklenmesini sıfırla"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr ""
 "Aygıtların yuvalara nasıl takıldığını sıfırlamak kimlik doğrulama "
 "gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
 msgstr "Sistemi kapat"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
 msgstr "Sistemi kapatmak için kimlik doğrulaması gerekiyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
 msgstr "Diğer kullanıcılar oturum açmışken sistemi kapat"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
@@ -298,11 +310,11 @@ msgstr ""
 "Diğer kullanıcılar oturum açmışken sistemi kapatmak kimlik doğrulaması "
 "gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
 msgstr "Bir uygulama engellenmesini isterken sistemi kapat"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
@@ -310,19 +322,19 @@ msgstr ""
 "Bir uygulama engellenmesini isterken sistemi kapatmak kimlik doğrulaması "
 "gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
 msgstr "Sistemi yeniden başlat"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
 msgstr "Sistemi yeniden başlatmak kimlik doğrulaması gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
 msgstr "Diğer kullanıcılar oturum açmışken sistemi yeniden başlat"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
@@ -330,11 +342,11 @@ msgstr ""
 "Diğer kullanıcılar oturum açmışken sistemi yeniden başlatmak kimlik "
 "doğrulaması gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
 msgstr "Bir uygulama engellenmesini isterken sistemi yeniden başlat"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
@@ -342,19 +354,19 @@ msgstr ""
 "Bir uygulama engellenmesini isterken sistemi yeniden başlatmak kimlik "
 "doğrulaması gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
 msgstr "Sistemi askıya al"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
 msgstr "Sistemi askıya almak kimlik doğrulaması gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
 msgstr "Diğer kullanıcılar oturum açmışken sistemi askıya al"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
@@ -362,11 +374,11 @@ msgstr ""
 "Diğer kullanıcılar oturum açmışken sistemi askıya almak kimlik doğrulaması "
 "gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
 msgstr "Bir uygulama engellenmesini isterken sistemi askıya al"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
@@ -374,19 +386,19 @@ msgstr ""
 "Bir uygulama engellenmesini isterken sistemi askıya almak kimlik doğrulaması "
 "gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
 msgstr "Sistemi hazırda beklet"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
 msgstr "Sistemi hazırda bekletmek kimlik doğrulaması gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
 msgstr "Diğer kullanıcılar oturum açmışken sistemi hazırda beklet"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
@@ -394,11 +406,11 @@ msgstr ""
 "Diğer kullanıcılar oturum açmışken sistemi hazırda bekletmek kimlik "
 "doğrulaması gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
 msgstr "Bir uygulama engellenmesini isterken sistemi hazırda beklet"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
@@ -406,33 +418,33 @@ msgstr ""
 "Bir uygulama engellenmesini isterken sistemi hazırda bekletmek kimlik "
 "doğrulaması gerektiriyor."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
 msgstr "Aktif oturumları, kullanıcıları ve yuvaları yönet"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
 "Aktif oturumları, kullanıcıları ve yuvaları yönetmek için kimlik doğrulaması "
 "gereklidir."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
 msgstr "Aktif oturumları kilitle ya da kilidini aç"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
 msgstr ""
 "Aktif oturumları kilitlemek ve bunların kilidini açmak için kimlik "
 "doğrulaması gereklidir."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
 msgstr ""
 "Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesine izin ver"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
@@ -440,11 +452,11 @@ msgstr ""
 "Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesi için kimlik "
 "doğrulaması gereklidir."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
 msgid "Set a wall message"
 msgstr "Bir duvar mesajı ayarla"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
 msgid "Authentication is required to set a wall message"
 msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir"
 
@@ -565,33 +577,33 @@ msgid ""
 msgstr ""
 "Ağ zaman eş zamanlamasını kontrol etmek kimlik doğrulaması gerektiriyor."
 
-#: ../src/core/dbus-unit.c:428
+#: ../src/core/dbus-unit.c:450
 msgid "Authentication is required to start '$(unit)'."
 msgstr "'$(unit)' başlatmak için kimlik doğrulaması gereklidir."
 
-#: ../src/core/dbus-unit.c:429
+#: ../src/core/dbus-unit.c:451
 msgid "Authentication is required to stop '$(unit)'."
 msgstr "'$(unit)' durdurmak için kimlik doğrulaması gereklidir."
 
-#: ../src/core/dbus-unit.c:430
+#: ../src/core/dbus-unit.c:452
 msgid "Authentication is required to reload '$(unit)'."
 msgstr "'$(unit)' yeniden yüklemek için kimlik doğrulaması gereklidir."
 
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
 msgid "Authentication is required to restart '$(unit)'."
 msgstr "'$(unit)' yeniden başlatmak için kimlik doğrulaması gereklidir."
 
-#: ../src/core/dbus-unit.c:535
+#: ../src/core/dbus-unit.c:560
 msgid "Authentication is required to kill '$(unit)'."
 msgstr "'$(unit)' sonlandırmak için kimlik doğrulaması gereklidir."
 
-#: ../src/core/dbus-unit.c:565
+#: ../src/core/dbus-unit.c:590
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr ""
 "'$(unit)'in \"failed\" (başarısız) durumunu sıfırlamak için kimlik "
 "doğrulaması gereklidir."
 
-#: ../src/core/dbus-unit.c:597
+#: ../src/core/dbus-unit.c:622
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr ""
 "'$(unit)' üzerindeki özellikleri ayarlamak için kimlik doğrulaması "
index 656d59c79ebf04b207ecb46ddd0df76a39041952..66044b8686bd27926b386daa1b9a90cf7e256893 100644 (file)
--- a/po/uk.po
+++ b/po/uk.po
@@ -2,21 +2,21 @@
 # Copyright (C) 2014 systemd's COPYRIGHT HOLDER
 # This file is distributed under the same license as the systemd package.
 # Eugene Melnik <jeka7js@gmail.com>, 2014.
-# Daniel Korostil <ted.korostiled@gmail.com>, 2014.
+# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2014-07-16 19:13+0300\n"
+"POT-Creation-Date: 2016-01-11 09:21+0200\n"
+"PO-Revision-Date: 2016-01-11 11:00+0300\n"
 "Last-Translator: Daniel Korostil <ted.korostiled@gmail.com>\n"
 "Language-Team: linux.org.ua\n"
 "Language: uk\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 "X-Generator: Virtaal 0.7.1\n"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
@@ -30,43 +30,42 @@ msgstr "Засвідчення потрібно, щоб надіслати вв
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
 msgid "Manage system services or other units"
-msgstr ""
+msgstr "Керувати системними службами й іншими одиницями"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
 msgid "Authentication is required to manage system services or other units."
-msgstr "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб керувати системними службами й іншими одиницями."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
 msgid "Manage system service or unit files"
-msgstr ""
+msgstr "Керувати системними службами й файлами одиниць"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
-#, fuzzy
 msgid "Authentication is required to manage system service or unit files."
-msgstr "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб керувати системними службами й файлами одиниць."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
-#, fuzzy
 msgid "Set or unset system and service manager environment variables"
-msgstr "Привілейований доступ до менеджера системи і служб"
+msgstr ""
+"Встановити або забрати змінну середовища з керування службами і системою"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
-#, fuzzy
 msgid ""
 "Authentication is required to set or unset system and service manager "
 "environment variables."
-msgstr "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб установити або забрати змінні середовища з "
+"керування службами і системою."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
-#, fuzzy
 msgid "Reload the systemd state"
-msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и Ñ\81иÑ\81Ñ\82емÑ\83"
+msgstr "Ð\9fеÑ\80езапÑ\83Ñ\81Ñ\82иÑ\82и Ñ\81Ñ\82ан Ñ\81иÑ\81Ñ\82еми"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
-#, fuzzy
 msgid "Authentication is required to reload the systemd state."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð²ÐºÐ°Ð·Ð°Ñ\82и Ñ\81иÑ\81Ñ\82емний Ñ\87аÑ\81."
+msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð¿ÐµÑ\80езапÑ\83Ñ\81Ñ\82иÑ\82и Ñ\81Ñ\82ан Ñ\81иÑ\81Ñ\82еми."
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
 msgid "Set host name"
@@ -98,30 +97,31 @@ msgstr "Засвідчення потрібно, щоб вказати лока
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:1
 msgid "Import a VM or container image"
-msgstr ""
+msgstr "Імпортувати образ контейнера або віртуальної машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to import a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати системний час."
+msgstr ""
+"Засвідчення потрібно, щоб імпортувати образ контейнера або віртуальної машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:3
 msgid "Export a VM or container image"
-msgstr ""
+msgstr "Експортувати образ контейнера або віртуальної машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:4
-#, fuzzy
 msgid "Authentication is required to export a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати системний час."
+msgstr ""
+"Засвідчення потрібно, щоб експортувати образ контейнера або віртуальної "
+"машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:5
 msgid "Download a VM or container image"
-msgstr ""
+msgstr "Звантажити образ контейнера або віртуальної машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:6
-#, fuzzy
 msgid "Authentication is required to download a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб звантажити образ контейнера або віртуальної машини"
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
 msgid "Set system locale"
@@ -277,7 +277,7 @@ msgstr "Засвідчення потрібно, щоб вимкнути сис
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system while other users are logged in"
-msgstr "Ð\92имикнÑ\83Ñ\82и Ñ\81иÑ\81Ñ\82емÑ\83, ÐºÐ¾Ð»Ð¸ Ñ\96нÑ\88Ñ\96 ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87Ñ\96 Ñ\89е Ð² Ð½Ñ\96й"
+msgstr "Вимкнути систему, коли інші користувачі ще в ній"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid ""
@@ -288,7 +288,7 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while an application asked to inhibit it"
-msgstr "Вимкнути систему, коли програми намагаються першкодити цьому"
+msgstr "Вимкнути систему, коли програми намагаються перешкодити цьому"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
@@ -296,7 +296,7 @@ msgid ""
 "asked to inhibit it."
 msgstr ""
 "Засвідчення потрібно, щоб вимкнути систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Reboot the system"
@@ -308,7 +308,7 @@ msgstr "Для перезавантаження системи необхідн
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system while other users are logged in"
-msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и, Ñ\8fкÑ\89о Ñ\96нÑ\89і користувачі в системі"
+msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и, Ñ\8fкÑ\89о Ñ\96нÑ\88і користувачі в системі"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid ""
@@ -319,7 +319,7 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while an application asked to inhibit it"
-msgstr "Перезапустити систему, коли програми намагаються першкодити цьому"
+msgstr "Перезапустити систему, коли програми намагаються перешкодити цьому"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
@@ -327,7 +327,7 @@ msgid ""
 "asked to inhibit it."
 msgstr ""
 "Засвідчення потрібно, щоб перезапустити систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Suspend the system"
@@ -350,15 +350,15 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while an application asked to inhibit it"
-msgstr "Призупинити систему, коли програми намагаються першкодити цьому"
+msgstr "Призупинити систему, коли програми намагаються перешкодити цьому"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
 msgstr ""
-"Засвідчення потрібно, щоб призупнити систему, коли програми намагаються "
-"першкодити цьому."
+"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð¿Ñ\80изÑ\83пиниÑ\82и Ñ\81иÑ\81Ñ\82емÑ\83, ÐºÐ¾Ð»Ð¸ Ð¿Ñ\80огÑ\80ами Ð½Ð°Ð¼Ð°Ð³Ð°Ñ\8eÑ\82Ñ\8cÑ\81Ñ\8f "
+"перешкодити цьому."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Hibernate the system"
@@ -381,7 +381,7 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while an application asked to inhibit it"
-msgstr "Приспати систему, коли програми намагаються першкодити цьому"
+msgstr "Приспати систему, коли програми намагаються перешкодити цьому"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
@@ -389,67 +389,118 @@ msgid ""
 "asked to inhibit it."
 msgstr ""
 "Засвідчення потрібно, щоб приспати систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Manage active sessions, users and seats"
-msgstr ""
+msgstr "Керувати сеансами, користувачами і робочими місцями"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:50
-#, fuzzy
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
-msgstr "Засвідчення потрібно, щоб під'єднувати пристрої до місць."
+msgstr ""
+"Засвідчення потрібно, щоб керувати сеансами, користувачами і робочими "
+"місцями."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Lock or unlock active sessions"
-msgstr ""
+msgstr "Заблокувати або розблокувати сеанси"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:52
-#, fuzzy
 msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð²ÐºÐ°Ð·Ð°Ñ\82и Ð»Ð¾ÐºÐ°Ð»Ñ\8cнÑ\83 Ñ\96нÑ\84оÑ\80маÑ\86Ñ\96Ñ\8e Ð¿Ñ\80о Ð¼Ð°Ñ\88ини."
+msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð·Ð°Ð±Ð»Ð¾ÐºÑ\83ваÑ\82и Ð°Ð±Ð¾ Ñ\80озблокÑ\83ваÑ\82и Ñ\81еанÑ\81и."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
+msgstr "Дозволити мікрокоду визначати, чи завантажувати інтерфейс встановлення"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:54
-#, fuzzy
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
-msgstr "Засвідчення потрібне, щоб встановити назву локального вузла."
+msgstr ""
+"Засвідчення потрібне, щоб дозволити мікрокоду визначати, чи завантажувати "
+"інтерфейс встановлення."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Вказати повідомлення на стіні"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "Засвідчення потрібне, щоб вказати повідомлення на стіні"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
-msgstr ""
+msgstr "Увійти в локальний контейнер"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to log into a local container."
-msgstr "Засвідчення потрібне, щоб встановити назву локального вузла."
+msgstr "Засвідчення потрібне, щоб увійти в локальний контейнер."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Manage local virtual machines and containers"
-msgstr ""
+msgid "Log into the local host"
+msgstr "Увійти в локальний вузол"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
-#, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "Засвідчення потрібне, щоб увійти в локальний вузол."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Перейняти оболонку в локальному контейнері"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Засвідчення потрібне, щоб перейняти оболонку в локальному контейнері."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Перейняти оболонку на локальному вузлі"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Засвідчення потрібне, щоб перейняти оболонку на локальному вузлі."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Перейняти псевдо TTY в локальному контейнері"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY в локальному контейнері."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Перейняти псевдо TTY на локальному вузлі"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY на локальному вузлі."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "Керувати локальними віртуальними машинами і контейнерами"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
-msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб керувати локальними віртуальними машинами і "
+"контейнерами."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
-msgstr ""
+msgstr "Керувати локальними образами віртуальних машин і контейнерів"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-#, fuzzy
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
-msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб керувати локальними образами віртуальних машин і "
+"контейнерів."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
 msgid "Set system time"
@@ -488,3 +539,31 @@ msgid ""
 msgstr ""
 "Засвідчення потрібно, щоб контролювати, чи синхронізування часу через мережу "
 "запущено."
+
+#: ../src/core/dbus-unit.c:449
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Засвідчення потрібно, щоб запустити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:450
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Засвідчення потрібно, щоб зупинити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:451
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Засвідчення потрібно, щоб перезавантажити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Засвідчення потрібно, щоб перезапустити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:556
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Засвідчення потрібне, щоб вбити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:586
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Засвідчення потрібне, щоб скинути «пошкоджений» стан з «$(unit)»."
+
+#: ../src/core/dbus-unit.c:618
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Засвідчення потрібно, щоб вказати властивості на «$(unit)»."
diff --git a/po/zh_CN.po b/po/zh_CN.po
new file mode 100644 (file)
index 0000000..10c53d4
--- /dev/null
@@ -0,0 +1,524 @@
+# Simplified Chinese translation for systemd.
+# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
+# This file is distributed under the same license as the systemd package.
+#
+# Frank Hill <hxf.prc@gmail.com>, 2014.
+# Boyuan Yang <073plan@gmail.com>, 2015.
+# Jeff Bai <jeffbai@aosc.xyz>, 2016.
+msgid ""
+msgstr ""
+"Project-Id-Version: systemd\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2015-10-27 02:24+0000\n"
+"PO-Revision-Date: 2016-03-01 20:38-0700\n"
+"Last-Translator: Jeff Bai <jeffbai@aosc.xyz>\n"
+"Language-Team: Chinese <i18n-zh@googlegroups.com>\n"
+"Language: zh_CN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.7.1\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+msgid "Send passphrase back to system"
+msgstr "将密码发回系统"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+msgid ""
+"Authentication is required to send the entered passphrase back to the system."
+msgstr "将输入的密码发回系统需要认证。"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+msgid "Manage system services or other units"
+msgstr "管理系统服务或其它单元"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+msgid "Authentication is required to manage system services or other units."
+msgstr "管理系统服务或其它单元需要认证。"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+msgid "Manage system service or unit files"
+msgstr "管理系统服务或单元文件"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+msgid "Authentication is required to manage system service or unit files."
+msgstr "管理系统服务或单元文件需要认证。"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+msgid "Set or unset system and service manager environment variables"
+msgstr "设置或清除系统及服务管理器的环境变量"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+msgid ""
+"Authentication is required to set or unset system and service manager "
+"environment variables."
+msgstr "设置或清除系统及服务管理器的环境变量需要认证。"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+msgid "Reload the systemd state"
+msgstr "重新载入 systemd 状态"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+msgid "Authentication is required to reload the systemd state."
+msgstr "重新载入 systemd 状态需要认证。"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+msgid "Set host name"
+msgstr "设置主机名"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+msgid "Authentication is required to set the local host name."
+msgstr "设置本地主机名需要认证。"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+msgid "Set static host name"
+msgstr "设置静态主机名"
+
+# For pretty hostname, the zh_CN/zh_TW translation should be discussed again.
+#
+# There were some discussions, like https://lists.fedoraprojects.org/pipermail/trans-zh_cn/2012-December/001347.html
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+#, fuzzy
+msgid ""
+"Authentication is required to set the statically configured local host name, "
+"as well as the pretty host name."
+msgstr "设置静态本地主机名或美观主机名需要认证。"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+msgid "Set machine information"
+msgstr "设置机器信息"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+msgid "Authentication is required to set local machine information."
+msgstr "设置本地机器信息需要认证。"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:1
+msgid "Import a VM or container image"
+msgstr "导入虚拟机或容器镜像"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:2
+msgid "Authentication is required to import a VM or container image"
+msgstr "导入虚拟机或容器镜像需要认证"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:3
+msgid "Export a VM or container image"
+msgstr "导出虚拟机或容器镜像"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:4
+msgid "Authentication is required to export a VM or container image"
+msgstr "导出虚拟机或容器镜像需要认证"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:5
+msgid "Download a VM or container image"
+msgstr "下载虚拟机或容器镜像"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:6
+msgid "Authentication is required to download a VM or container image"
+msgstr "下载虚拟机或容器镜像需要认证。"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+msgid "Set system locale"
+msgstr "设置系统区域和语言"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+msgid "Authentication is required to set the system locale."
+msgstr "设置系统区域和语言需要认证。"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+msgid "Set system keyboard settings"
+msgstr "设置系统键盘"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+msgid "Authentication is required to set the system keyboard settings."
+msgstr "设置系统键盘需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:1
+msgid "Allow applications to inhibit system shutdown"
+msgstr "允许应用程序阻止系统关机"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:2
+msgid ""
+"Authentication is required for an application to inhibit system shutdown."
+msgstr "允许应用程序阻止系统关机需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:3
+msgid "Allow applications to delay system shutdown"
+msgstr "允许应用程序延迟系统关机"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:4
+msgid "Authentication is required for an application to delay system shutdown."
+msgstr "允许应用程序延迟系统关机需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:5
+msgid "Allow applications to inhibit system sleep"
+msgstr "允许应用程序阻止系统睡眠"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:6
+msgid "Authentication is required for an application to inhibit system sleep."
+msgstr "允许应用程序阻止系统睡眠需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:7
+msgid "Allow applications to delay system sleep"
+msgstr "允许应用程序延迟系统睡眠"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:8
+msgid "Authentication is required for an application to delay system sleep."
+msgstr "允许应用程序延迟系统睡眠需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:9
+msgid "Allow applications to inhibit automatic system suspend"
+msgstr "允许应用程序阻止系统自动挂起"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:10
+msgid ""
+"Authentication is required for an application to inhibit automatic system "
+"suspend."
+msgstr "允许应用程序阻止系统自动挂起需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:11
+msgid "Allow applications to inhibit system handling of the power key"
+msgstr "允许应用程序阻止系统响应电源键"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:12
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the power key."
+msgstr "允许应用程序阻止系统响应电源键需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:13
+msgid "Allow applications to inhibit system handling of the suspend key"
+msgstr "允许应用程序阻止系统响应挂起键"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:14
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the suspend key."
+msgstr "允许应用程序阻止系统响应挂起键需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:15
+msgid "Allow applications to inhibit system handling of the hibernate key"
+msgstr "允许应用程序阻止系统响应挂起键"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:16
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the hibernate key."
+msgstr "允许应用程序阻止系统响应挂起键需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:17
+msgid "Allow applications to inhibit system handling of the lid switch"
+msgstr "允许应用程序阻止系统响应笔记本上盖开关事件"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:18
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the lid switch."
+msgstr "允许应用程序阻止系统响应笔记本上盖开关事件需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in users to run programs"
+msgstr "允许未登录用户运行程序"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Authentication is required to run programs as a non-logged-in user."
+msgstr "允许未登录用户运行程序需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow attaching devices to seats"
+msgstr "允许将设备附加至会话座位"
+
+# Pay attention to the concept of "seat".
+#
+# To fully understand the meaning, please refer to session management in old ConsoleKit and new systemd-logind.
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
+msgid "Authentication is required for attaching a device to a seat."
+msgstr "允许将设备附加至某个会话座位需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
+msgid "Flush device to seat attachments"
+msgstr "刷新设备至会话座位间的连接"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
+msgid ""
+"Authentication is required for resetting how devices are attached to seats."
+msgstr "重新设定设备的会话座位接入方式时需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
+msgid "Power off the system"
+msgstr "关闭系统"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
+msgid "Authentication is required for powering off the system."
+msgstr "关闭系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
+msgid "Power off the system while other users are logged in"
+msgstr "存在其他已登录用户时仍然关机"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
+msgid ""
+"Authentication is required for powering off the system while other users are "
+"logged in."
+msgstr "存在其他已登录用户时关闭系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
+msgid "Power off the system while an application asked to inhibit it"
+msgstr "有其它应用程序阻止时仍然关机"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
+msgid ""
+"Authentication is required for powering off the system while an application "
+"asked to inhibit it."
+msgstr "在其它应用程序阻止关机时关闭系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
+msgid "Reboot the system"
+msgstr "重启系统"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
+msgid "Authentication is required for rebooting the system."
+msgstr "重启系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
+msgid "Reboot the system while other users are logged in"
+msgstr "存在其他已登录用户时仍然重启"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
+msgid ""
+"Authentication is required for rebooting the system while other users are "
+"logged in."
+msgstr "存在其他已登录用户时重启系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
+msgid "Reboot the system while an application asked to inhibit it"
+msgstr "有其它应用程序阻止时仍然重启"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
+msgid ""
+"Authentication is required for rebooting the system while an application "
+"asked to inhibit it."
+msgstr "在其它应用程序阻止重启时重启系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
+msgid "Suspend the system"
+msgstr "挂起系统"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
+msgid "Authentication is required for suspending the system."
+msgstr "挂起系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Suspend the system while other users are logged in"
+msgstr "存在其他已登录用户时仍然挂起系统"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid ""
+"Authentication is required for suspending the system while other users are "
+"logged in."
+msgstr "存在其他已登录用户时挂起系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Suspend the system while an application asked to inhibit it"
+msgstr "有其它应用程序阻止时仍然挂起系统"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for suspending the system while an application "
+"asked to inhibit it."
+msgstr "在其它应用程序阻止挂起时挂起系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Hibernate the system"
+msgstr "休眠系统"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid "Authentication is required for hibernating the system."
+msgstr "休眠系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
+msgid "Hibernate the system while other users are logged in"
+msgstr "存在其他已登录用户时仍然休眠"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
+msgid ""
+"Authentication is required for hibernating the system while other users are "
+"logged in."
+msgstr "存在其他已登录用户时进行休眠系统需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
+msgid "Hibernate the system while an application asked to inhibit it"
+msgstr "有其它应用程序阻止时仍然休眠"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid ""
+"Authentication is required for hibernating the system while an application "
+"asked to inhibit it."
+msgstr "在其它应用程序阻止休眠时进行休眠需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
+msgid "Manage active sessions, users and seats"
+msgstr "管理活动会话、用户与会话座位"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
+msgid ""
+"Authentication is required for managing active sessions, users and seats."
+msgstr "管理活动会话、用户与会话座位需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
+msgid "Lock or unlock active sessions"
+msgstr "锁定或解锁活动会话"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
+msgid "Authentication is required to lock or unlock active sessions."
+msgstr "对活动会话进行锁定或解锁需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
+msgid "Allow indication to the firmware to boot to setup interface"
+msgstr "允许向固件发出指示以启动至设置界面"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid ""
+"Authentication is required to indicate to the firmware to boot to setup "
+"interface."
+msgstr "向固件发出启动时进入设置界面的指令需要认证。"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "设置 wall 消息"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "设置 wall 消息需要认证。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+msgid "Log into a local container"
+msgstr "登入本地容器"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+msgid "Authentication is required to log into a local container."
+msgstr "登录一个本地容器需要认证。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "登入本地主机"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "登入本地主机需要认证。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "在本地容器中获取一个 shell"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "在本地容器中获取 shell 需要认证。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "在本地主机中获取一个 shell"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "在本地主机中获取 shell 需要认证。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "在本地容器中获取一个假 TTY"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "在本地容器中获取假 TTY 需要认证。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "在本地主机中获取一个假 TTY"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "在本地主机中获取假 TTY 需要认证。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "管理本地虚拟机和容器"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+msgid ""
+"Authentication is required to manage local virtual machines and containers."
+msgstr "管理本地虚拟机和容器需要认证。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+msgid "Manage local virtual machine and container images"
+msgstr "管理本地虚拟机和容器的镜像"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+msgid ""
+"Authentication is required to manage local virtual machine and container "
+"images."
+msgstr "管理本地的虚拟机和容器镜像需要认证。"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+msgid "Set system time"
+msgstr "设置系统时间"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+msgid "Authentication is required to set the system time."
+msgstr "设置系统时间需要认证。"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+msgid "Set system timezone"
+msgstr "设置系统时区"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+msgid "Authentication is required to set the system timezone."
+msgstr "设置系统时区需要认证。"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+msgid "Set RTC to local timezone or UTC"
+msgstr "设置硬件时钟使用本地时间或 UTC"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+msgid ""
+"Authentication is required to control whether the RTC stores the local or "
+"UTC time."
+msgstr "设置硬件时钟使用本地时间或 UTC 需要认证。"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+msgid "Turn network time synchronization on or off"
+msgstr "打开或关闭网络时间同步"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+msgid ""
+"Authentication is required to control whether network time synchronization "
+"shall be enabled."
+msgstr "打开或关闭网络时间同步需要认证。"
+
+#: ../src/core/dbus-unit.c:430
+msgid "Authentication is required to start '$(unit)'."
+msgstr "启动“$(unit)”需要认证。"
+
+#: ../src/core/dbus-unit.c:431
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "停止“$(unit)”需要认证。"
+
+#: ../src/core/dbus-unit.c:432
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "重新载入“$(unit)”需要认证。"
+
+#: ../src/core/dbus-unit.c:433 ../src/core/dbus-unit.c:434
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "重新启动“$(unit)”需要认证。"
+
+#: ../src/core/dbus-unit.c:537
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "杀死“$(unit)”需要认证。"
+
+#: ../src/core/dbus-unit.c:567
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "重置“$(unit)”的失败(\"failed\")状态需要认证。"
+
+#: ../src/core/dbus-unit.c:599
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "设置“$(unit)”的属性需要认证。"
index ff2914cb838ae265702f9f6c7e484326f249837a..affea9126ec4bbca402106b089a8d3a3a5be110d 100644 (file)
@@ -1,21 +1,21 @@
 # Traditional Chinese translation for systemd.
 # Copyright (C) 2015 systemd's COPYRIGHT HOLDER
 # This file is distributed under the same license as the systemd package.
-# Jeff Huang <s8321414@gmail.com>, 2015.
+# Jeff Huang <s8321414@gmail.com>, 2015, 2016.
 msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-11-22 16:37+0100\n"
-"PO-Revision-Date: 2015-06-11 12:44+0800\n"
-"Last-Translator: Jeff Huang <s8321414@gmail.com>\n"
+"PO-Revision-Date: 2016-02-12 11:46+0800\n"
+"Last-Translator: Jeff Huang <s8321414@chakraos.org>\n"
 "Language-Team: chinese-l10n <chinese-l10n@googlegroups.com>\n"
 "Language: zh_TW\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Lokalize 1.5\n"
+"X-Generator: Lokalize 2.0\n"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
 msgid "Send passphrase back to system"
@@ -375,12 +375,11 @@ msgstr "對韌體的指示以開始設定介面需要驗證。"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Set a wall message"
-msgstr ""
+msgstr "設定 wall 訊息"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:56
-#, fuzzy
 msgid "Authentication is required to set a wall message"
-msgstr "設定主機名稱需要驗證。"
+msgstr "設定 wall 訊息需要驗證。"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
@@ -391,53 +390,45 @@ msgid "Authentication is required to log into a local container."
 msgstr "登入到本機容器需要驗證。"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-#, fuzzy
 msgid "Log into the local host"
-msgstr "登入到本機容器"
+msgstr "登入到本機主機"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
-#, fuzzy
 msgid "Authentication is required to log into the local host."
-msgstr "登入到本機容器需要驗證。"
+msgstr "登入到本機主機需要驗證。"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
-#, fuzzy
 msgid "Acquire a shell in a local container"
-msgstr "登入到本機容器"
+msgstr "在本機容器中取得一個 shell"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-#, fuzzy
 msgid "Authentication is required to acquire a shell in a local container."
-msgstr "登入到本機容器需要驗證。"
+msgstr "在本機容器中取得一個 shell 需要驗證。"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
 msgid "Acquire a shell on the local host"
-msgstr ""
+msgstr "在本機主機中取得一個 shell"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
-#, fuzzy
 msgid "Authentication is required to acquire a shell on the local host."
-msgstr "設定主機名稱需要驗證。"
+msgstr "在本機主機中取得一個 shell 需要驗證。"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
-#, fuzzy
 msgid "Acquire a pseudo TTY in a local container"
-msgstr "登入到本機容器"
+msgstr "取得在本機容器中的偽 TTY"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
-#, fuzzy
 msgid ""
 "Authentication is required to acquire a pseudo TTY in a local container."
-msgstr "登入到本機容器需要驗證。"
+msgstr "取得在本機容器中的偽 TTY 需要驗證。"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
 msgid "Acquire a pseudo TTY on the local host"
-msgstr ""
+msgstr "取得在本機主機中的偽 TTY"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
-#, fuzzy
 msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr "設定主機名稱需要驗證。"
+msgstr "取得在本機主機中的偽 TTY 需要驗證。"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
@@ -495,36 +486,30 @@ msgid ""
 msgstr "控制網路時間同步是否啟用需要驗證。"
 
 #: ../src/core/dbus-unit.c:428
-#, fuzzy
 msgid "Authentication is required to start '$(unit)'."
-msgstr "設定系統時間需要驗證。"
+msgstr "啟動 '$(unit)' 需要驗證。"
 
 #: ../src/core/dbus-unit.c:429
-#, fuzzy
 msgid "Authentication is required to stop '$(unit)'."
-msgstr "設定系統時間需要驗證。"
+msgstr "停止 '$(unit)' 需要驗證。"
 
 #: ../src/core/dbus-unit.c:430
-#, fuzzy
 msgid "Authentication is required to reload '$(unit)'."
-msgstr "重新載入 elogind 狀態需要驗證。"
+msgstr "重新載入 '$(unit)' 需要驗證。"
 
 #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
-#, fuzzy
 msgid "Authentication is required to restart '$(unit)'."
-msgstr "設定系統時間需要驗證。"
+msgstr "重新啟動 '$(unit)' 需要驗證。"
 
 #: ../src/core/dbus-unit.c:535
-#, fuzzy
 msgid "Authentication is required to kill '$(unit)'."
-msgstr "ç\99»å\85¥å\88°æ\9c¬æ©\9f容å\99¨需要驗證。"
+msgstr "ç \8dé\99¤ '$(unit)' 需要驗證。"
 
 #: ../src/core/dbus-unit.c:565
-#, fuzzy
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
-msgstr "設定主機名稱需要驗證。"
+msgstr "重置 '$(unit)' 的「失敗」狀態需要驗證。"
 
 #: ../src/core/dbus-unit.c:597
-#, fuzzy
 msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "設定系統時間需要驗證。"
+msgstr "在 '$(unit)' 上設定屬性需要驗證。"
+
index e6ac2d7b8af42cdecc26c40355f864417ed9581e..bea726814f419b4b26ad80a9be95f60fcfc6e7a9 100644 (file)
@@ -6,3 +6,72 @@ org.freedesktop.systemd1.policy
 99-systemd.rules
 *.gcno
 *.gcda
+
+# directories not needed by elogind
+/initctl
+/libudev
+/cgls
+/rfkill
+/resolve
+/firstboot
+/path
+/tmpfiles
+/quotacheck
+/system-update-generator
+/debug-generator
+/sysctl
+/sysv-generator
+/backlight
+/coredump
+/modules-load
+/machine-id-setup
+/getty-generator
+/ac-power
+/gpt-auto-generator
+/journal
+/socket-proxy
+/test
+/cgtop
+/locale
+/cryptsetup
+/run
+/binfmt
+/fstab-generator
+/detect-virt
+/timesync
+/journal-remote
+/nss-mymachines
+/nss-resolve
+/hibernate-resume
+/stdio-bridge
+/hostname
+/user-sessions
+/nss-myhostname
+/random-seed
+/vconsole
+/analyze
+/sysusers
+/notify
+/kernel-install
+/rc-local-generator
+/nspawn
+/boot
+/import
+/libsystemd
+/escape
+/systemctl
+/hwdb
+/network
+/udev
+/tty-ask-password-agent
+/remount-fs
+/ask-password
+/timedate
+/delta
+/dbus1-generator
+/fsck
+/machine
+/update-done
+/libsystemd-network
+/reply-password
+/activate
index a16f97c3d429350dbcf320485f2b5c68406aff56..b540dcddf589fafb0b4de1cccbd162c5b10ad90e 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdint.h>
+#include <string.h>
+
 #include "alloc-util.h"
+#include "macro.h"
 #include "util.h"
 
 void* memdup(const void *p, size_t l) {
index 679ba7f398727a7a951711ec3d523bd4fca4922a..ceeee519b79f864ccbf359fede0c91c3364c7e36 100644 (file)
@@ -51,25 +51,29 @@ static inline void freep(void *p) {
 
 #define _cleanup_free_ _cleanup_(freep)
 
-_malloc_  _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
-        if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+static inline bool size_multiply_overflow(size_t size, size_t need) {
+        return _unlikely_(need != 0 && size > (SIZE_MAX / need));
+}
+
+_malloc_  _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
+        if (size_multiply_overflow(size, need))
                 return NULL;
 
-        return malloc(a * b);
+        return malloc(size * need);
 }
 
-_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) {
-        if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) {
+        if (size_multiply_overflow(size, need))
                 return NULL;
 
-        return realloc(p, a * b);
+        return realloc(p, size * need);
 }
 
-_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) {
-        if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
+        if (size_multiply_overflow(size, need))
                 return NULL;
 
-        return memdup(p, a * b);
+        return memdup(p, size * need);
 }
 
 void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
index 3506ca8bffaf0c1b1085c3121c2b10d76e4deffb..5e53f447d03b63c18906000f58687926c503e484 100644 (file)
@@ -101,6 +101,39 @@ int cg_read_pid(FILE *f, pid_t *_pid) {
         return 1;
 }
 
+int cg_read_event(const char *controller, const char *path, const char *event,
+                  char **val)
+{
+        _cleanup_free_ char *events = NULL, *content = NULL;
+        char *p, *line;
+        int r;
+
+        r = cg_get_path(controller, path, "cgroup.events", &events);
+        if (r < 0)
+                return r;
+
+        r = read_full_file(events, &content, NULL);
+        if (r < 0)
+                return r;
+
+        p = content;
+        while ((line = strsep(&p, "\n"))) {
+                char *key;
+
+                key = strsep(&line, " ");
+                if (!key || !line)
+                        return -EINVAL;
+
+                if (strcmp(key, event))
+                        continue;
+
+                *val = strdup(line);
+                return 0;
+        }
+
+        return -ENOENT;
+}
+
 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
         _cleanup_free_ char *fs = NULL;
         int r;
@@ -164,7 +197,15 @@ int cg_rmdir(const char *controller, const char *path) {
         return 0;
 }
 
-int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
+int cg_kill(
+                const char *controller,
+                const char *path,
+                int sig,
+                CGroupFlags flags,
+                Set *s,
+                cg_kill_log_func_t log_kill,
+                void *userdata) {
+
         _cleanup_set_free_ Set *allocated_set = NULL;
         bool done = false;
         int r, ret = 0;
@@ -172,6 +213,11 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
 
         assert(sig >= 0);
 
+         /* Don't send SIGCONT twice. Also, SIGKILL always works even when process is suspended, hence don't send
+          * SIGCONT on SIGKILL. */
+        if (IN_SET(sig, SIGCONT, SIGKILL))
+                flags &= ~CGROUP_SIGCONT;
+
         /* This goes through the tasks list and kills them all. This
          * is repeated until no further processes are added to the
          * tasks list, to properly handle forking processes */
@@ -199,19 +245,22 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
 
                 while ((r = cg_read_pid(f, &pid)) > 0) {
 
-                        if (ignore_self && pid == my_pid)
+                        if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid)
                                 continue;
 
                         if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid))
                                 continue;
 
+                        if (log_kill)
+                                log_kill(pid, sig, userdata);
+
                         /* If we haven't killed this process yet, kill
                          * it */
                         if (kill(pid, sig) < 0) {
                                 if (ret >= 0 && errno != ESRCH)
                                         ret = -errno;
                         } else {
-                                if (sigcont && sig != SIGKILL)
+                                if (flags & CGROUP_SIGCONT)
                                         (void) kill(pid, SIGCONT);
 
                                 if (ret == 0)
@@ -245,7 +294,15 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
         return ret;
 }
 
-int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
+int cg_kill_recursive(
+                const char *controller,
+                const char *path,
+                int sig,
+                CGroupFlags flags,
+                Set *s,
+                cg_kill_log_func_t log_kill,
+                void *userdata) {
+
         _cleanup_set_free_ Set *allocated_set = NULL;
         _cleanup_closedir_ DIR *d = NULL;
         int r, ret;
@@ -260,7 +317,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
                         return -ENOMEM;
         }
 
-        ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
+        ret = cg_kill(controller, path, sig, flags, s, log_kill, userdata);
 
         r = cg_enumerate_subgroups(controller, path, &d);
         if (r < 0) {
@@ -278,15 +335,14 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
                 if (!p)
                         return -ENOMEM;
 
-                r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
+                r = cg_kill_recursive(controller, p, sig, flags, s, log_kill, userdata);
                 if (r != 0 && ret >= 0)
                         ret = r;
         }
-
         if (ret >= 0 && r < 0)
                 ret = r;
 
-        if (rem) {
+        if (flags & CGROUP_REMOVE) {
                 r = cg_rmdir(controller, path);
                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
                         return r;
@@ -295,7 +351,13 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
         return ret;
 }
 
-int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
+int cg_migrate(
+                const char *cfrom,
+                const char *pfrom,
+                const char *cto,
+                const char *pto,
+                CGroupFlags flags) {
+
         bool done = false;
         _cleanup_set_free_ Set *s = NULL;
         int r, ret = 0;
@@ -314,8 +376,8 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
 
         log_debug_elogind("Migrating \"%s\"/\"%s\" to \"%s\"/\"%s\" (%s)",
                           cfrom, pfrom, cto, pto,
-                          ignore_self ? "ignoring self" : "watching self");
-
+                          (flags & CGROUP_IGNORE_SELF)
+                          ? "ignoring self" : "watching self");
         do {
                 _cleanup_fclose_ FILE *f = NULL;
                 pid_t pid = 0;
@@ -334,7 +396,7 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
                         /* This might do weird stuff if we aren't a
                          * single-threaded program. However, we
                          * luckily know we are not */
-                        if (ignore_self && pid == my_pid)
+                        if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid)
                                 continue;
 
                         if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid))
@@ -382,8 +444,7 @@ int cg_migrate_recursive(
                 const char *pfrom,
                 const char *cto,
                 const char *pto,
-                bool ignore_self,
-                bool rem) {
+                CGroupFlags flags) {
 
         _cleanup_closedir_ DIR *d = NULL;
         int r, ret = 0;
@@ -394,7 +455,7 @@ int cg_migrate_recursive(
         assert(cto);
         assert(pto);
 
-        ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
+        ret = cg_migrate(cfrom, pfrom, cto, pto, flags);
 
         r = cg_enumerate_subgroups(cfrom, pfrom, &d);
         if (r < 0) {
@@ -410,9 +471,9 @@ int cg_migrate_recursive(
                 p = strjoin(pfrom, "/", fn, NULL);
                 free(fn);
                 if (!p)
-                                return -ENOMEM;
+                        return -ENOMEM;
 
-                r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
+                r = cg_migrate_recursive(cfrom, p, cto, pto, flags);
                 if (r != 0 && ret >= 0)
                         ret = r;
         }
@@ -420,7 +481,7 @@ int cg_migrate_recursive(
         if (r < 0 && ret >= 0)
                 ret = r;
 
-        if (rem) {
+        if (flags & CGROUP_REMOVE) {
                 r = cg_rmdir(cfrom, pfrom);
                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
                         return r;
@@ -434,8 +495,7 @@ int cg_migrate_recursive_fallback(
                 const char *pfrom,
                 const char *cto,
                 const char *pto,
-                bool ignore_self,
-                bool rem) {
+                CGroupFlags flags) {
 
         int r;
 
@@ -444,7 +504,7 @@ int cg_migrate_recursive_fallback(
         assert(cto);
         assert(pto);
 
-        r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem);
+        r = cg_migrate_recursive(cfrom, pfrom, cto, pto, flags);
         if (r < 0) {
                 char prefix[strlen(pto) + 1];
 
@@ -453,7 +513,7 @@ int cg_migrate_recursive_fallback(
                 PATH_FOREACH_PREFIX(prefix, pto) {
                         int q;
 
-                        q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
+                        q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, flags);
                         if (q >= 0)
                                 return q;
                 }
@@ -494,14 +554,14 @@ static int join_path_legacy(const char *controller, const char *path, const char
                 t = strjoin("/sys/fs/cgroup/", dn, "/", suffix, NULL);
         else if (isempty(suffix))
                 t = strjoin("/sys/fs/cgroup/", dn, "/", path, NULL);
-                else
+        else
                 t = strjoin("/sys/fs/cgroup/", dn, "/", path, "/", suffix, NULL);
         if (!t)
                 return -ENOMEM;
 
         *fs = t;
         return 0;
-        }
+}
 
 static int join_path_unified(const char *path, const char *suffix, char **fs) {
         char *t;
@@ -1016,18 +1076,12 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
                 return unified;
 
         if (unified > 0) {
-                _cleanup_free_ char *populated = NULL, *t = NULL;
+                _cleanup_free_ char *t = NULL;
 
                 /* On the unified hierarchy we can check empty state
-                 * via the "cgroup.populated" attribute. */
-
-                r = cg_get_path(controller, path, "cgroup.populated", &populated);
-                if (r < 0)
-                        return r;
+                 * via the "populated" attribute of "cgroup.events". */
 
-                r = read_one_line_file(populated, &t);
-                if (r == -ENOENT)
-                        return 1;
+                r = cg_read_event(controller, path, "populated", &t);
                 if (r < 0)
                         return r;
 
@@ -1041,8 +1095,8 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
                         return r;
 
                 r = cg_enumerate_subgroups(controller, path, &d);
-                        if (r == -ENOENT)
-                                return 1;
+                if (r == -ENOENT)
+                        return 1;
                 if (r < 0)
                         return r;
 
@@ -1267,7 +1321,7 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
 }
 
 #if 0 /// UNNEEDED by elogind
-int cg_path_decode_unit(const char *cgroup, char **unit){
+int cg_path_decode_unit(const char *cgroup, char **unit) {
         char *c, *s;
         size_t n;
 
@@ -1518,9 +1572,7 @@ int cg_pid_get_machine_name(pid_t pid, char **machine) {
 #endif // 0
 
 int cg_path_get_session(const char *path, char **session) {
-        /* Elogind uses a flat hierarchy, just "/SESSION".  The only
-           wrinkle is that SESSION might be escaped.  */
-#if 0
+#if 0 /// UNNEEDED by elogind
         _cleanup_free_ char *unit = NULL;
         char *start, *end;
         int r;
@@ -1542,6 +1594,8 @@ int cg_path_get_session(const char *path, char **session) {
         if (!session_id_valid(start))
                 return -ENXIO;
 #else
+        /* Elogind uses a flat hierarchy, just "/SESSION".  The only
+           wrinkle is that SESSION might be escaped.  */
         const char *e, *n, *start;
 
         assert(path);
@@ -1872,7 +1926,6 @@ int cg_set_attribute(const char *controller, const char *path, const char *attri
         return write_string_file(p, value, 0);
 }
 
-#if 0 /// UNNEEDED by elogind
 int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) {
         _cleanup_free_ char *p = NULL;
         int r;
@@ -1884,6 +1937,7 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri
         return read_one_line_file(p, ret);
 }
 
+#if 0 /// UNNEEDED by elogind
 int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) {
         CGroupController c;
         int r, unified;
@@ -1936,16 +1990,16 @@ int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_m
 
         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
                 CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
-                        const char *p = NULL;
+                const char *p = NULL;
 
                 if (!(supported & bit))
                         continue;
 
-                        if (path_callback)
-                                p = path_callback(bit, userdata);
+                if (path_callback)
+                        p = path_callback(bit, userdata);
 
-                        if (!p)
-                                p = path;
+                if (!p)
+                        p = path;
 
                 (void) cg_attach_fallback(cgroup_controller_to_string(c), p, pid);
         }
@@ -1975,7 +2029,7 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
         int r = 0, unified;
 
         if (!path_equal(from, to))  {
-                r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
+                r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, CGROUP_REMOVE);
                 if (r < 0)
                         return r;
         }
@@ -1988,18 +2042,18 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
 
         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
                 CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
-                        const char *p = NULL;
+                const char *p = NULL;
 
                 if (!(supported & bit))
                         continue;
 
-                        if (to_callback)
-                                p = to_callback(bit, userdata);
+                if (to_callback)
+                        p = to_callback(bit, userdata);
 
-                        if (!p)
-                                p = to;
+                if (!p)
+                        p = to;
 
-                (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, false, false);
+                (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, 0);
         }
 
         return 0;
@@ -2079,12 +2133,12 @@ int cg_mask_supported(CGroupMask *ret) {
                                 continue;
 
                         mask |= CGROUP_CONTROLLER_TO_MASK(v);
-        }
+                }
 
-                /* Currently, we only support the memory and pids
+                /* Currently, we only support the memory, io and pids
                  * controller in the unified hierarchy, mask
                  * everything else off. */
-                mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_PIDS;
+                mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS;
 
         } else {
                 CGroupController c;
@@ -2179,21 +2233,21 @@ int cg_unified(void) {
         if (statfs("/sys/fs/cgroup/", &fs) < 0)
                 return -errno;
 
-/// elogind can not support the unified hierarchy as a controller,
-/// so always assume a classical hierarchy.
-/// If, ond only *if*, someone really wants to substitute systemd-login
-/// in an environment managed by systemd with elogin, we might have to
-/// add such a support.
-#if 0
-        if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC))
+#if 0 /// UNNEEDED by elogind
+        if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC))
                 unified_cache = true;
         else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
 #else
+        /* elogind can not support the unified hierarchy as a controller,
+         * so always assume a classical hierarchy.
+         * If, and only *if*, someone really wants to substitute systemd-login
+         * in an environment managed by systemd with elogind, we might have to
+         * add such a support. */
         if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
 #endif // 0
                 unified_cache = false;
         else
-                return -ENOEXEC;
+                return -ENOMEDIUM;
 
         return unified_cache;
 }
@@ -2288,6 +2342,42 @@ bool cg_is_legacy_wanted(void) {
 #endif // 0
 
 #if 0 /// UNNEEDED by elogind
+int cg_weight_parse(const char *s, uint64_t *ret) {
+        uint64_t u;
+        int r;
+
+        if (isempty(s)) {
+                *ret = CGROUP_WEIGHT_INVALID;
+                return 0;
+        }
+
+        r = safe_atou64(s, &u);
+        if (r < 0)
+                return r;
+
+        if (u < CGROUP_WEIGHT_MIN || u > CGROUP_WEIGHT_MAX)
+                return -ERANGE;
+
+        *ret = u;
+        return 0;
+}
+
+const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX] = {
+        [CGROUP_IO_RBPS_MAX]    = CGROUP_LIMIT_MAX,
+        [CGROUP_IO_WBPS_MAX]    = CGROUP_LIMIT_MAX,
+        [CGROUP_IO_RIOPS_MAX]   = CGROUP_LIMIT_MAX,
+        [CGROUP_IO_WIOPS_MAX]   = CGROUP_LIMIT_MAX,
+};
+
+static const char* const cgroup_io_limit_type_table[_CGROUP_IO_LIMIT_TYPE_MAX] = {
+        [CGROUP_IO_RBPS_MAX]    = "IOReadBandwidthMax",
+        [CGROUP_IO_WBPS_MAX]    = "IOWriteBandwidthMax",
+        [CGROUP_IO_RIOPS_MAX]   = "IOReadIOPSMax",
+        [CGROUP_IO_WIOPS_MAX]   = "IOWriteIOPSMax",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(cgroup_io_limit_type, CGroupIOLimitType);
+
 int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
         uint64_t u;
         int r;
@@ -2332,6 +2422,7 @@ int cg_blkio_weight_parse(const char *s, uint64_t *ret) {
 static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
         [CGROUP_CONTROLLER_CPU] = "cpu",
         [CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
+        [CGROUP_CONTROLLER_IO] = "io",
         [CGROUP_CONTROLLER_BLKIO] = "blkio",
         [CGROUP_CONTROLLER_MEMORY] = "memory",
         [CGROUP_CONTROLLER_DEVICES] = "devices",
index f1a52b2bda75ac73d0b2a5bc57f982d6e1176328..56598d22bde8b1de244d4729ecb6ea129b1377f6 100644 (file)
@@ -34,6 +34,7 @@
 typedef enum CGroupController {
         CGROUP_CONTROLLER_CPU,
         CGROUP_CONTROLLER_CPUACCT,
+        CGROUP_CONTROLLER_IO,
         CGROUP_CONTROLLER_BLKIO,
         CGROUP_CONTROLLER_MEMORY,
         CGROUP_CONTROLLER_DEVICES,
@@ -48,6 +49,7 @@ typedef enum CGroupController {
 typedef enum CGroupMask {
         CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU),
         CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT),
+        CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO),
         CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO),
         CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
         CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES),
@@ -56,6 +58,37 @@ typedef enum CGroupMask {
 } CGroupMask;
 
 #if 0 /// UNNEEDED by elogind
+/* Special values for all weight knobs on unified hierarchy */
+#define CGROUP_WEIGHT_INVALID ((uint64_t) -1)
+#define CGROUP_WEIGHT_MIN UINT64_C(1)
+#define CGROUP_WEIGHT_MAX UINT64_C(10000)
+#define CGROUP_WEIGHT_DEFAULT UINT64_C(100)
+
+#define CGROUP_LIMIT_MIN UINT64_C(0)
+#define CGROUP_LIMIT_MAX ((uint64_t) -1)
+
+static inline bool CGROUP_WEIGHT_IS_OK(uint64_t x) {
+        return
+            x == CGROUP_WEIGHT_INVALID ||
+            (x >= CGROUP_WEIGHT_MIN && x <= CGROUP_WEIGHT_MAX);
+}
+
+/* IO limits on unified hierarchy */
+typedef enum CGroupIOLimitType {
+        CGROUP_IO_RBPS_MAX,
+        CGROUP_IO_WBPS_MAX,
+        CGROUP_IO_RIOPS_MAX,
+        CGROUP_IO_WIOPS_MAX,
+
+        _CGROUP_IO_LIMIT_TYPE_MAX,
+        _CGROUP_IO_LIMIT_TYPE_INVALID = -1
+} CGroupIOLimitType;
+
+extern const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX];
+
+const char* cgroup_io_limit_type_to_string(CGroupIOLimitType t) _const_;
+CGroupIOLimitType cgroup_io_limit_type_from_string(const char *s) _pure_;
+
 /* Special values for the cpu.shares attribute */
 #define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
 #define CGROUP_CPU_SHARES_MIN UINT64_C(2)
@@ -98,16 +131,26 @@ static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) {
 
 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
 int cg_read_pid(FILE *f, pid_t *_pid);
+int cg_read_event(const char *controller, const char *path, const char *event,
+                  char **val);
 
 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
 int cg_read_subgroup(DIR *d, char **fn);
 
-int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s);
-int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool remove, Set *s);
+typedef enum CGroupFlags {
+        CGROUP_SIGCONT     = 1,
+        CGROUP_IGNORE_SELF = 2,
+        CGROUP_REMOVE      = 4,
+} CGroupFlags;
+
+typedef void (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata);
+
+int cg_kill(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata);
+int cg_kill_recursive(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata);
 
-int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self);
-int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove);
-int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem);
+int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
+int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
+int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
 
 int cg_split_spec(const char *spec, char **controller, char **path);
 int cg_mangle_path(const char *path, char **result);
@@ -127,12 +170,13 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid);
 int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
 
 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value);
-#if 0 /// UNNEEDED by elogind
 int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret);
 
+#if 0 /// UNNEEDED by elogind
 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
 #endif // 0
+
 int cg_install_release_agent(const char *controller, const char *agent);
 int cg_uninstall_release_agent(const char *controller);
 
@@ -150,6 +194,7 @@ int cg_path_get_machine_name(const char *path, char **machine);
 int cg_path_get_slice(const char *path, char **slice);
 int cg_path_get_user_slice(const char *path, char **slice);
 #endif // 0
+
 int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted);
 int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup);
 
@@ -164,10 +209,12 @@ int cg_pid_get_user_slice(pid_t pid, char **slice);
 
 int cg_path_decode_unit(const char *cgroup, char **unit);
 #endif // 0
+
 char *cg_escape(const char *p);
 char *cg_unescape(const char *p) _pure_;
 
 bool cg_controller_is_valid(const char *p);
+
 #if 0 /// UNNEEDED by elogind
 int cg_slice_to_path(const char *unit, char **ret);
 
@@ -180,10 +227,13 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
 int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root);
 int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p);
 #endif // 0
+
 int cg_mask_supported(CGroupMask *ret);
+
 #if 0 /// UNNEEDED by elogind
 int cg_kernel_controllers(Set *controllers);
 #endif // 0
+
 int cg_unified(void);
 #if 0 /// UNNEEDED by elogind
 void cg_unified_flush(void);
@@ -194,7 +244,9 @@ bool cg_is_legacy_wanted(void);
 
 const char* cgroup_controller_to_string(CGroupController c) _const_;
 CGroupController cgroup_controller_from_string(const char *s) _pure_;
+
 #if 0 /// UNNEEDED by elogind
+int cg_weight_parse(const char *s, uint64_t *ret);
 int cg_cpu_shares_parse(const char *s, uint64_t *ret);
 int cg_blkio_weight_parse(const char *s, uint64_t *ret);
 #endif // 0
index 6be7cc37a4519fb00748762af5a0dc9a4666ce82..4e5f392fe59fdc8b7a74bbdb84ea482a117f916d 100644 (file)
 //#include "umask-util.h"
 //#include "xattr-util.h"
 
-#define COPY_BUFFER_SIZE (16*1024)
+#define COPY_BUFFER_SIZE (16*1024u)
+
+static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
+                                   int fd_out, loff_t *off_out,
+                                   size_t len,
+                                   unsigned int flags) {
+        static int have = -1;
+        ssize_t r;
+
+        if (have == false)
+                return -ENOSYS;
+
+        r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
+        if (_unlikely_(have < 0))
+                have = r >= 0 || errno != ENOSYS;
+        if (r >= 0)
+                return r;
+        else
+                return -errno;
+}
 
 int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
-        bool try_sendfile = true, try_splice = true;
+        bool try_cfr = true, try_sendfile = true, try_splice = true;
         int r;
+        size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */
 
         assert(fdf >= 0);
         assert(fdt >= 0);
+
 #if 0 /// UNNEEDED by elogind
         /* Try btrfs reflinks first. */
         if (try_reflink &&
@@ -66,57 +87,71 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
                         return 0; /* we copied the whole thing, hence hit EOF, return 0 */
         }
 #endif // 0
+
         for (;;) {
-                size_t m = COPY_BUFFER_SIZE;
                 ssize_t n;
 
                 if (max_bytes != (uint64_t) -1) {
-
                         if (max_bytes <= 0)
                                 return 1; /* return > 0 if we hit the max_bytes limit */
 
-                        if ((uint64_t) m > max_bytes)
-                                m = (size_t) max_bytes;
+                        if (m > max_bytes)
+                                m = max_bytes;
+                }
+
+                /* First try copy_file_range(), unless we already tried */
+                if (try_cfr) {
+                        n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
+                        if (n < 0) {
+                                if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF))
+                                        return n;
+
+                                try_cfr = false;
+                                /* use fallback below */
+                        } else if (n == 0) /* EOF */
+                                break;
+                        else
+                                /* Success! */
+                                goto next;
                 }
 
                 /* First try sendfile(), unless we already tried */
                 if (try_sendfile) {
-
                         n = sendfile(fdt, fdf, NULL, m);
                         if (n < 0) {
-                                if (errno != EINVAL && errno != ENOSYS)
+                                if (!IN_SET(errno, EINVAL, ENOSYS))
                                         return -errno;
 
                                 try_sendfile = false;
                                 /* use fallback below */
                         } else if (n == 0) /* EOF */
                                 break;
-                        else if (n > 0)
+                        else
                                 /* Success! */
                                 goto next;
                 }
 
-                /* The try splice, unless we already tried */
+                /* Then try splice, unless we already tried */
                 if (try_splice) {
-                        n  = splice(fdf, NULL, fdt, NULL, m, 0);
+                        n = splice(fdf, NULL, fdt, NULL, m, 0);
                         if (n < 0) {
-                                if (errno != EINVAL && errno != ENOSYS)
+                                if (!IN_SET(errno, EINVAL, ENOSYS))
                                         return -errno;
 
                                 try_splice = false;
                                 /* use fallback below */
                         } else if (n == 0) /* EOF */
                                 break;
-                        else if (n > 0)
+                        else
                                 /* Success! */
                                 goto next;
                 }
 
                 /* As a fallback just copy bits by hand */
                 {
-                        uint8_t buf[m];
+                        uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
 
-                        n = read(fdf, buf, m);
+                        n = read(fdf, buf, sizeof buf);
                         if (n < 0)
                                 return -errno;
                         if (n == 0) /* EOF */
@@ -132,6 +167,11 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
                         assert(max_bytes >= (uint64_t) n);
                         max_bytes -= n;
                 }
+                /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
+                 * so reduce our maximum by the amount we already copied,
+                 * but don't go below our copy buffer size, unless we are
+                 * close the limit of bytes we are allowed to copy. */
+                m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
         }
 
         return 0; /* return 0 if we hit EOF earlier than the size limit */
@@ -267,6 +307,8 @@ static int fd_copy_directory(
                 fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         else
                 fdf = fcntl(df, F_DUPFD_CLOEXEC, 3);
+        if (fdf < 0)
+                return -errno;
 
         d = fdopendir(fdf);
         if (!d)
@@ -287,22 +329,6 @@ static int fd_copy_directory(
 
         r = 0;
 
-        if (created) {
-                struct timespec ut[2] = {
-                        st->st_atim,
-                        st->st_mtim
-                };
-
-                if (fchown(fdt, st->st_uid, st->st_gid) < 0)
-                        r = -errno;
-
-                if (fchmod(fdt, st->st_mode & 07777) < 0)
-                        r = -errno;
-
-                (void) futimens(fdt, ut);
-                (void) copy_xattr(dirfd(d), fdt);
-        }
-
         FOREACH_DIRENT_ALL(de, d, return -errno) {
                 struct stat buf;
                 int q;
@@ -326,7 +352,7 @@ static int fd_copy_directory(
                         q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name);
                 else if (S_ISFIFO(buf.st_mode))
                         q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name);
-                else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode))
+                else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode) || S_ISSOCK(buf.st_mode))
                         q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name);
                 else
                         q = -EOPNOTSUPP;
@@ -338,6 +364,22 @@ static int fd_copy_directory(
                         r = q;
         }
 
+        if (created) {
+                struct timespec ut[2] = {
+                        st->st_atim,
+                        st->st_mtim
+                };
+
+                if (fchown(fdt, st->st_uid, st->st_gid) < 0)
+                        r = -errno;
+
+                if (fchmod(fdt, st->st_mode & 07777) < 0)
+                        r = -errno;
+
+                (void) copy_xattr(dirfd(d), fdt);
+                (void) futimens(fdt, ut);
+        }
+
         return r;
 }
 
@@ -358,7 +400,7 @@ int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge)
                 return fd_copy_symlink(fdf, from, &st, fdt, to);
         else if (S_ISFIFO(st.st_mode))
                 return fd_copy_fifo(fdf, from, &st, fdt, to);
-        else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
+        else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || S_ISSOCK(st.st_mode))
                 return fd_copy_node(fdf, from, &st, fdt, to);
         else
                 return -EOPNOTSUPP;
@@ -369,7 +411,6 @@ int copy_tree(const char *from, const char *to, bool merge) {
 }
 
 int copy_directory_fd(int dirfd, const char *to, bool merge) {
-
         struct stat st;
 
         assert(dirfd >= 0);
@@ -384,6 +425,21 @@ int copy_directory_fd(int dirfd, const char *to, bool merge) {
         return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, merge);
 }
 
+int copy_directory(const char *from, const char *to, bool merge) {
+        struct stat st;
+
+        assert(from);
+        assert(to);
+
+        if (lstat(from, &st) < 0)
+                return -errno;
+
+        if (!S_ISDIR(st.st_mode))
+                return -ENOTDIR;
+
+        return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, merge);
+}
+
 int copy_file_fd(const char *from, int fdt, bool try_reflink) {
         _cleanup_close_ int fdf = -1;
         int r;
index c389724aa001538955b7977dbade05ca89a9d611..41aad741c9aa5fb1aeaf864dde97945bd2a9590c 100644 (file)
@@ -31,6 +31,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace
 int copy_tree(const char *from, const char *to, bool merge);
 int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge);
 int copy_directory_fd(int dirfd, const char *to, bool merge);
+int copy_directory(const char *from, const char *to, bool merge);
 #endif // 0
 int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink);
 #if 0 /// UNNEEDED by elogind
index 31753e6005f4de452c6be1b98170096d37de0b93..bc7826f7b82e65bae59a859a8b39857ff97d39a6 100644 (file)
@@ -40,8 +40,6 @@
 #define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
 #define SIGNALS_IGNORE SIGPIPE
 
-#define REBOOT_PARAM_FILE "/run/systemd/reboot-param"
-
 #ifdef HAVE_SPLIT_USR
 #define KBD_KEYMAP_DIRS                         \
         "/usr/share/keymaps/\0"                 \
index 5fb535cb13a2a55f86170747a9d4752b4f400864..59067121b74f0c93c56a27673eeb1c7cfa109e12 100644 (file)
@@ -52,12 +52,10 @@ int dirent_ensure_type(DIR *d, struct dirent *de) {
 bool dirent_is_file(const struct dirent *de) {
         assert(de);
 
-        if (hidden_file(de->d_name))
+        if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
                 return false;
 
-        if (de->d_type != DT_REG &&
-            de->d_type != DT_LNK &&
-            de->d_type != DT_UNKNOWN)
+        if (hidden_or_backup_file(de->d_name))
                 return false;
 
         return true;
@@ -66,12 +64,10 @@ bool dirent_is_file(const struct dirent *de) {
 bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
         assert(de);
 
-        if (de->d_type != DT_REG &&
-            de->d_type != DT_LNK &&
-            de->d_type != DT_UNKNOWN)
+        if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
                 return false;
 
-        if (hidden_file_allow_backup(de->d_name))
+        if (de->d_name[0] == '.')
                 return false;
 
         return endswith(de->d_name, suffix);
index 6bf099b46c0a51ba6cb304aecfaf1e02d045d828..b91d04908f9a01545ed7f68e4f32fbc91323288d 100644 (file)
@@ -38,7 +38,7 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pu
                                 on_error;                               \
                         }                                               \
                         break;                                          \
-                } else if (hidden_file((de)->d_name))                   \
+                } else if (hidden_or_backup_file((de)->d_name))         \
                         continue;                                       \
                 else
 
index 564149306c91a310d2af1d72ac229e4c67b32c65..127ca2ecb2ced04c1d5a81177f7f8a6e536edbd4 100644 (file)
@@ -414,6 +414,34 @@ char *xescape(const char *s, const char *bad) {
 }
 
 #if 0 /// UNNEEDED by elogind
+char *octescape(const char *s, size_t len) {
+        char *r, *t;
+        const char *f;
+
+        /* Escapes all chars in bad, in addition to \ and " chars,
+         * in \nnn style escaping. */
+
+        r = new(char, len * 4 + 1);
+        if (!r)
+                return NULL;
+
+        for (f = s, t = r; f < s + len; f++) {
+
+                if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
+                        *(t++) = '\\';
+                        *(t++) = '0' + (*f >> 6);
+                        *(t++) = '0' + ((*f >> 3) & 8);
+                        *(t++) = '0' + (*f & 8);
+                } else
+                        *(t++) = *f;
+        }
+
+        *t = 0;
+
+        return r;
+
+}
+
 static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
         assert(bad);
 
index f57438038019f33120d46aa24556bab5997550db..8383c75869b8b7cbe5df5bacc0eb80fbfce57183 100644 (file)
@@ -48,8 +48,9 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
 int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
 
 char *xescape(const char *s, const char *bad);
-
 #if 0 /// UNNEEDED by elogind
+char *octescape(const char *s, size_t len);
+
 char *shell_escape(const char *s, const char *bad);
 char *shell_maybe_quote(const char *s);
 #endif // 0
index 97a02220c3e9183d251c8b715d800197e2e537b1..bace3c183671e373a83bcf4ce4655a631b0bb8de 100644 (file)
@@ -63,12 +63,12 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                 if (!GREEDY_REALLOC(s, allocated, sz+1))
                         return -ENOMEM;
 
-        for (;; (*p) ++, c = **p) {
+        for (;; (*p)++, c = **p) {
                 if (c == 0)
                         goto finish_force_terminate;
                 else if (strchr(separators, c)) {
                         if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
-                                (*p) ++;
+                                (*p)++;
                                 goto finish_force_next;
                         }
                 } else {
@@ -81,7 +81,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                 }
         }
 
-        for (;; (*p) ++, c = **p) {
+        for (;; (*p)++, c = **p) {
                 if (backslash) {
                         if (!GREEDY_REALLOC(s, allocated, sz+7))
                                 return -ENOMEM;
@@ -129,7 +129,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                         backslash = false;
 
                 } else if (quote) {     /* inside either single or double quotes */
-                        for (;; (*p) ++, c = **p) {
+                        for (;; (*p)++, c = **p) {
                                 if (c == 0) {
                                         if (flags & EXTRACT_RELAX)
                                                 goto finish_force_terminate;
@@ -149,7 +149,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                         }
 
                 } else {
-                        for (;; (*p) ++, c = **p) {
+                        for (;; (*p)++, c = **p) {
                                 if (c == 0)
                                         goto finish_force_terminate;
                                 else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
@@ -160,11 +160,11 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                                         break;
                                 } else if (strchr(separators, c)) {
                                         if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
-                                                (*p) ++;
+                                                (*p)++;
                                                 goto finish_force_next;
                                         }
                                         /* Skip additional coalesced separators. */
-                                        for (;; (*p) ++, c = **p) {
+                                        for (;; (*p)++, c = **p) {
                                                 if (c == 0)
                                                         goto finish_force_terminate;
                                                 if (!strchr(separators, c))
index 6c3063298b21e688bf6ff9cd722a628a9178764b..3eb3324b57bc2ae53ecbca7e4baf65be3c3f50ab 100644 (file)
@@ -186,6 +186,12 @@ int fd_cloexec(int fd, bool cloexec) {
         return 0;
 }
 
+void stdio_unset_cloexec(void) {
+        fd_cloexec(STDIN_FILENO, false);
+        fd_cloexec(STDOUT_FILENO, false);
+        fd_cloexec(STDERR_FILENO, false);
+}
+
 _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
         unsigned i;
 
@@ -231,7 +237,7 @@ int close_all_fds(const int except[], unsigned n_except) {
         while ((de = readdir(d))) {
                 int fd = -1;
 
-                if (hidden_file(de->d_name))
+                if (hidden_or_backup_file(de->d_name))
                         continue;
 
                 if (safe_atoi(de->d_name, &fd) < 0)
@@ -359,4 +365,18 @@ bool fdname_is_valid(const char *s) {
 
         return p - s < 256;
 }
+
+int fd_get_path(int fd, char **ret) {
+        char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+        int r;
+
+        xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+
+        r = readlink_malloc(procfs_path, ret);
+
+        if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
+                return -EBADF;
+
+        return r;
+}
 #endif // 0
index e2f5bbdaf80a8c217833efeba3549d5430be6673..fe92b76c405c5880987e31dea53ff16076f61649 100644 (file)
@@ -65,6 +65,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
 
 int fd_nonblock(int fd, bool nonblock);
 int fd_cloexec(int fd, bool cloexec);
+void stdio_unset_cloexec(void);
 
 int close_all_fds(const int except[], unsigned n_except);
 
@@ -74,6 +75,8 @@ int same_fd(int a, int b);
 void cmsg_close_all(struct msghdr *mh);
 
 bool fdname_is_valid(const char *s);
+
+int fd_get_path(int fd, char **ret);
 #endif // 0
 
 /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
index 25262efb86b985aa4e35b7788da360c8064371f0..4deeef252eb32a936306a22a674ccad28c36165b 100644 (file)
@@ -25,7 +25,6 @@
 #include "fileio.h"
 
 int write_string_file_atomic_label(const char *fn, const char *line);
-
 #if 0 /// UNNEEDED by elogind
 int write_env_file_label(const char *fname, char **l);
 int fopen_temporary_label(const char *target,
index 3bb1d3e036dd3b10796ef99c3bb3a4fbf865b2aa..df432eaee4283f9c182fa01301e48cffc869fb13 100644 (file)
@@ -352,7 +352,7 @@ static int parse_env_file_internal(
                 case KEY:
                         if (strchr(newline, c)) {
                                 state = PRE_KEY;
-                                line ++;
+                                line++;
                                 n_key = 0;
                         } else if (c == '=') {
                                 state = PRE_VALUE;
@@ -376,7 +376,7 @@ static int parse_env_file_internal(
                 case PRE_VALUE:
                         if (strchr(newline, c)) {
                                 state = PRE_KEY;
-                                line ++;
+                                line++;
                                 key[n_key] = 0;
 
                                 if (value)
@@ -416,7 +416,7 @@ static int parse_env_file_internal(
                 case VALUE:
                         if (strchr(newline, c)) {
                                 state = PRE_KEY;
-                                line ++;
+                                line++;
 
                                 key[n_key] = 0;
 
@@ -535,7 +535,7 @@ static int parse_env_file_internal(
                                 state = COMMENT_ESCAPE;
                         else if (strchr(newline, c)) {
                                 state = PRE_KEY;
-                                line ++;
+                                line++;
                         }
                         break;
 
@@ -588,7 +588,7 @@ static int parse_env_file_push(
         va_list aq, *ap = userdata;
 
         if (!utf8_is_valid(key)) {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = utf8_escape_invalid(key);
                 log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p);
@@ -596,7 +596,7 @@ static int parse_env_file_push(
         }
 
         if (value && !utf8_is_valid(value)) {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = utf8_escape_invalid(value);
                 log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p);
@@ -880,13 +880,13 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
 
                 do {
                         t = strstr(t, pattern);
-        if (!t)
-                return -ENOENT;
+                        if (!t)
+                                return -ENOENT;
 
                         /* Check that pattern occurs in beginning of line. */
                         pattern_ok = (t == status || t[-1] == '\n');
 
-        t += strlen(pattern);
+                        t += strlen(pattern);
 
                 } while (!pattern_ok);
 
@@ -910,7 +910,7 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
                 /* Back off one char if there's nothing but whitespace
                    and zeros */
                 if (!*t || isspace(*t))
-                        t --;
+                        t--;
         }
 
         len = strcspn(t, terminator);
@@ -1071,9 +1071,9 @@ int fflush_and_check(FILE *f) {
         return 0;
 }
 
-/* This is much like like mkostemp() but is subject to umask(). */
+/* This is much like mkostemp() but is subject to umask(). */
 int mkostemp_safe(char *pattern, int flags) {
-        _cleanup_umask_ mode_t u;
+        _cleanup_umask_ mode_t u = 0;
         int fd;
 
         assert(pattern);
@@ -1087,32 +1087,6 @@ int mkostemp_safe(char *pattern, int flags) {
         return fd;
 }
 
-#if 0 /// UNNEEDED by elogind
-int open_tmpfile(const char *path, int flags) {
-        char *p;
-        int fd;
-
-        assert(path);
-
-#ifdef O_TMPFILE
-        /* Try O_TMPFILE first, if it is supported */
-        fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
-        if (fd >= 0)
-                return fd;
-#endif
-
-        /* Fall back to unguessable name + unlinking */
-        p = strjoina(path, "/systemd-tmp-XXXXXX");
-
-        fd = mkostemp_safe(p, flags);
-        if (fd < 0)
-                return fd;
-
-        unlink(p);
-        return fd;
-}
-#endif // 0
-
 int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
         const char *fn;
         char *t;
@@ -1145,7 +1119,6 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
         return 0;
 }
 
-#if 0 /// UNNEEDED by elogind
 int tempfn_random(const char *p, const char *extra, char **ret) {
         const char *fn;
         char *t, *x;
@@ -1188,6 +1161,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
         return 0;
 }
 
+#if 0 /// UNNEEDED by elogind
 int tempfn_random_child(const char *p, const char *extra, char **ret) {
         char *t, *x;
         uint64_t u;
@@ -1285,4 +1259,146 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
 
         return fputs(s, f);
 }
+
+int open_tmpfile_unlinkable(const char *directory, int flags) {
+        char *p;
+        int fd;
+
+        if (!directory)
+                directory = "/tmp";
+
+        /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
+
+#ifdef O_TMPFILE
+        /* Try O_TMPFILE first, if it is supported */
+        fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
+        if (fd >= 0)
+                return fd;
+#endif
+
+        /* Fall back to unguessable name + unlinking */
+        p = strjoina(directory, "/systemd-tmp-XXXXXX");
+
+        fd = mkostemp_safe(p, flags);
+        if (fd < 0)
+                return fd;
+
+        (void) unlink(p);
+
+        return fd;
+}
+
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
+        _cleanup_free_ char *tmp = NULL;
+        int r, fd;
+
+        assert(target);
+        assert(ret_path);
+
+        /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
+        assert((flags & O_EXCL) == 0);
+
+        /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
+         * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
+         * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
+
+#ifdef O_TMPFILE
+        {
+                _cleanup_free_ char *dn = NULL;
+
+                dn = dirname_malloc(target);
+                if (!dn)
+                        return -ENOMEM;
+
+                fd = open(dn, O_TMPFILE|flags, 0640);
+                if (fd >= 0) {
+                        *ret_path = NULL;
+                        return fd;
+                }
+
+                log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
+        }
+#endif
+
+        r = tempfn_random(target, NULL, &tmp);
+        if (r < 0)
+                return r;
+
+        fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
+        if (fd < 0)
+                return -errno;
+
+        *ret_path = tmp;
+        tmp = NULL;
+
+        return fd;
+}
+
+int link_tmpfile(int fd, const char *path, const char *target) {
+
+        assert(fd >= 0);
+        assert(target);
+
+        /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
+         * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
+         * on the directory, and renameat2() is used instead.
+         *
+         * Note that in both cases we will not replace existing files. This is because linkat() does not support this
+         * operation currently (renameat2() does), and there is no nice way to emulate this. */
+
+        if (path) {
+                if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
+                        return -errno;
+        } else {
+                char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+
+                xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
+
+                if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
+                        return -errno;
+        }
+
+        return 0;
+}
 #endif // 0
+
+int read_nul_string(FILE *f, char **ret) {
+        _cleanup_free_ char *x = NULL;
+        size_t allocated = 0, n = 0;
+
+        assert(f);
+        assert(ret);
+
+        /* Reads a NUL-terminated string from the specified file. */
+
+        for (;;) {
+                int c;
+
+                if (!GREEDY_REALLOC(x, allocated, n+2))
+                        return -ENOMEM;
+
+                c = fgetc(f);
+                if (c == 0) /* Terminate at NUL byte */
+                        break;
+                if (c == EOF) {
+                        if (ferror(f))
+                                return -errno;
+                        break; /* Terminate at EOF */
+                }
+
+                x[n++] = (char) c;
+        }
+
+        if (x)
+                x[n] = 0;
+        else {
+                x = new0(char, 1);
+                if (!x)
+                        return -ENOMEM;
+        }
+
+        *ret = x;
+        x = NULL;
+
+        return 0;
+}
index 0635147b756d38c9fe96c6fe48d7ab82a3118714..2469b4ca4d9fff3b78577c73d06015806c6fbbd2 100644 (file)
@@ -62,6 +62,7 @@ DIR *xopendirat(int dirfd, const char *name, int flags);
 int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
 int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
 #endif // 0
+
 #define FOREACH_LINE(line, f, on_error)                         \
         for (;;)                                                \
                 if (!fgets(line, sizeof(line), f)) {            \
@@ -75,17 +76,21 @@ int fflush_and_check(FILE *f);
 
 int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
 int mkostemp_safe(char *pattern, int flags);
-#if 0 /// UNNEEDED by elogind
-int open_tmpfile(const char *path, int flags);
-#endif // 0
 
 int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
-#if 0 /// UNNEEDED by elogind
 int tempfn_random(const char *p, const char *extra, char **ret);
+#if 0 /// UNNEEDED by elogind
 int tempfn_random_child(const char *p, const char *extra, char **ret);
 
 int write_timestamp_file_atomic(const char *fn, usec_t n);
 int read_timestamp_file(const char *fn, usec_t *ret);
 
 int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
+
+int open_tmpfile_unlinkable(const char *directory, int flags);
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
+
+int link_tmpfile(int fd, const char *path, const char *target);
 #endif // 0
+
+int read_nul_string(FILE *f, char **ret);
index ce516b117dfc027845c6ace62c9f5b1994367de3..39a185f59b4affffedc8044b556a4ab019edcd95 100644 (file)
@@ -49,7 +49,7 @@
 #if SIZEOF_TIME_T == 8
 #  define PRI_TIME PRIi64
 #elif SIZEOF_TIME_T == 4
-#  define PRI_TIME PRIu32
+#  define PRI_TIME "li"
 #else
 #  error Unknown time_t size
 #endif
 #else
 #  error Unknown rlim_t size
 #endif
+
+#if SIZEOF_DEV_T == 8
+#  define DEV_FMT "%" PRIu64
+#elif SIZEOF_DEV_T == 4
+#  define DEV_FMT "%" PRIu32
+#else
+#  error Unknown dev_t size
+#endif
+
+#if SIZEOF_INO_T == 8
+#  define INO_FMT "%" PRIu64
+#elif SIZEOF_INO_T == 4
+#  define INO_FMT "%" PRIu32
+#else
+#  error Unknown ino_t size
+#endif
index b37fef8f525d69abbb31268e13f603507890c470..d2d7bb566f1324969997f4060a35d18a8bc9f929 100644 (file)
@@ -287,26 +287,6 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
         return 0;
 }
 
-#if 0 /// UNNEEDED by elogind
-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 (mode != MODE_INVALID)
-                if (fchmod(fd, mode) < 0)
-                        return -errno;
-
-        if (uid != UID_INVALID || gid != GID_INVALID)
-                if (fchown(fd, uid, gid) < 0)
-                        return -errno;
-
-        return 0;
-}
-#endif // 0
-
 int fchmod_umask(int fd, mode_t m) {
         mode_t u;
         int r;
@@ -519,3 +499,47 @@ int get_files_in_directory(const char *path, char ***list) {
 
         return n;
 }
+
+#if 0 /// UNNEEDED by elogind
+int var_tmp(char **ret) {
+        const char *tmp_dir = NULL;
+        const char *env_tmp_dir = NULL;
+        char *c = NULL;
+        int r;
+
+        assert(ret);
+
+        env_tmp_dir = getenv("TMPDIR");
+        if (env_tmp_dir != NULL) {
+                r = is_dir(env_tmp_dir, true);
+                if (r < 0 && r != -ENOENT)
+                        return r;
+                if (r > 0)
+                        tmp_dir = env_tmp_dir;
+        }
+
+        if (!tmp_dir)
+                tmp_dir = "/var/tmp";
+
+        c = strdup(tmp_dir);
+        if (!c)
+                return -ENOMEM;
+        *ret = c;
+
+        return 0;
+}
+
+int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
+        char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+        int r;
+
+        /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
+        xsprintf(path, "/proc/self/fd/%i", what);
+
+        r = inotify_add_watch(fd, path, mask);
+        if (r < 0)
+                return -errno;
+
+        return r;
+}
+#endif // 0
index 2000b38a96738230e43df68dca4c802750ee8117..ab31f061e13745fc8037ebcb51a034e48a06ab6d 100644 (file)
 #include "time-util.h"
 
 int unlink_noerrno(const char *path);
+
 #if 0 /// UNNEEDED by elogind
 int rmdir_parents(const char *path, const char *stop);
 
 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
 #endif // 0
+
 int readlinkat_malloc(int fd, const char *p, char **ret);
 int readlink_malloc(const char *p, char **r);
 #if 0 /// UNNEEDED by elogind
@@ -43,10 +45,9 @@ int readlink_and_make_absolute(const char *p, char **r);
 int readlink_and_canonicalize(const char *p, char **r);
 int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
 #endif // 0
+
 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
-#if 0 /// UNNEEDED by elogind
-int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
-#endif // 0
+
 int fchmod_umask(int fd, mode_t mode);
 
 int fd_warn_permissions(const char *path, int fd);
@@ -60,6 +61,7 @@ int fd_warn_permissions(const char *path, int fd);
 
 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
 int touch(const char *path);
+
 #if 0 /// UNNEEDED by elogind
 int symlink_idempotent(const char *from, const char *to);
 
@@ -67,9 +69,12 @@ int symlink_atomic(const char *from, const char *to);
 int mknod_atomic(const char *path, mode_t mode, dev_t dev);
 int mkfifo_atomic(const char *path, mode_t mode);
 #endif // 0
+
 int get_files_in_directory(const char *path, char ***list);
 
 #if 0 /// UNNEEDED by elogind
+int var_tmp(char **ret);
+
 #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
 
 #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
@@ -81,4 +86,6 @@ union inotify_event_buffer {
         struct inotify_event ev;
         uint8_t raw[INOTIFY_EVENT_MAX];
 };
+
+int inotify_add_watch_fd(int fd, int what, uint32_t mask);
 #endif // 0
index b03aa431603c64a834d596a4962b9c83bdbca81e..5975bc8fc9c9507ad00ad518136adadc30487be8 100644 (file)
@@ -1,11 +1,11 @@
+#pragma once
+
 /* gunicode.h - Unicode manipulation functions
  *
  *  Copyright (C) 1999, 2000 Tom Tromey
  *  Copyright 2000, 2005 Red Hat, Inc.
  */
 
-#pragma once
-
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
index d7b61ceaee311dc8a7655518b8bb8e5a97d36a72..c3a4a011b5be7f231ad46c584432853049be156e 100644 (file)
@@ -1,21 +1,21 @@
 /***
-  This file is part of elogind.
+  This file is part of systemd.
 
   Copyright 2010 Lennart Poettering
   Copyright 2014 Michal Schmidt
 
-  elogind is free software; you can redistribute it and/or modify it
+  systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
 
-  elogind is distributed in the hope that it will be useful, but
+  systemd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
 #include "hash-funcs.h"
index 01be3ca70782de1a03bd5d1daa45cc92265f152e..299189d143d7e3bc19c93448795b36039b947ffb 100644 (file)
@@ -1,23 +1,23 @@
 #pragma once
 
 /***
-  This file is part of elogind.
+  This file is part of systemd.
 
   Copyright 2010 Lennart Poettering
   Copyright 2014 Michal Schmidt
 
-  elogind is free software; you can redistribute it and/or modify it
+  systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
 
-  elogind is distributed in the hope that it will be useful, but
+  systemd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
 #include "macro.h"
index a9f82b6af74d98fa5ca76ca2c74a2bcddf26e47a..250fed5345fc47befcf09df9ea952626f1f956d2 100644 (file)
@@ -176,7 +176,7 @@ enum HashmapType {
 };
 
 struct _packed_ indirect_storage {
-        char    *storage;                  /* where buckets and DIBs are stored */
+        void *storage;                     /* where buckets and DIBs are stored */
         uint8_t  hash_key[HASH_KEY_SIZE];  /* hash key; changes during resize */
 
         unsigned n_entries;                /* number of stored entries */
@@ -193,7 +193,7 @@ struct direct_storage {
         /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
          * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
          *              or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
-        char storage[sizeof(struct indirect_storage)];
+        uint8_t storage[sizeof(struct indirect_storage)];
 };
 
 #define DIRECT_BUCKETS(entry_t) \
@@ -302,7 +302,7 @@ static void n_entries_dec(HashmapBase *h) {
                 h->n_direct_entries--;
 }
 
-static char *storage_ptr(HashmapBase *h) {
+static void *storage_ptr(HashmapBase *h) {
         return h->has_indirect ? h->indirect.storage
                                : h->direct.storage;
 }
@@ -347,7 +347,7 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) {
 
 static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) {
         return (struct hashmap_base_entry*)
-                (storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
+                ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
 }
 
 static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) {
@@ -381,7 +381,7 @@ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_
 
 static dib_raw_t *dib_raw_ptr(HashmapBase *h) {
         return (dib_raw_t*)
-                (storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
+                ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
 }
 
 static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) {
@@ -1028,7 +1028,7 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
  */
 static int resize_buckets(HashmapBase *h, unsigned entries_add) {
         struct swap_entries swap;
-        char *new_storage;
+        void *new_storage;
         dib_raw_t *old_dibs, *new_dibs;
         const struct hashmap_type_info *hi;
         unsigned idx, optimal_idx;
@@ -1095,7 +1095,7 @@ static int resize_buckets(HashmapBase *h, unsigned entries_add) {
         h->indirect.n_buckets = (1U << new_shift) /
                                 (hi->entry_size + sizeof(dib_raw_t));
 
-        old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets);
+        old_dibs = (dib_raw_t*)((uint8_t*) new_storage + hi->entry_size * old_n_buckets);
         new_dibs = dib_raw_ptr(h);
 
         /*
@@ -1768,6 +1768,9 @@ void *ordered_hashmap_next(OrderedHashmap *h, const void *key) {
 int set_consume(Set *s, void *value) {
         int r;
 
+        assert(s);
+        assert(value);
+
         r = set_put(s, value);
         if (r <= 0)
                 free(value);
@@ -1777,20 +1780,18 @@ int set_consume(Set *s, void *value) {
 
 int set_put_strdup(Set *s, const char *p) {
         char *c;
-        int r;
 
         assert(s);
         assert(p);
 
+        if (set_contains(s, (char*) p))
+                return 0;
+
         c = strdup(p);
         if (!c)
                 return -ENOMEM;
 
-        r = set_consume(s, c);
-        if (r == -EEXIST)
-                return 0;
-
-        return r;
+        return set_consume(s, c);
 }
 
 #if 0 /// UNNEEDED by elogind
@@ -1798,6 +1799,8 @@ int set_put_strdupv(Set *s, char **l) {
         int n = 0, r;
         char **i;
 
+        assert(s);
+
         STRV_FOREACH(i, l) {
                 r = set_put_strdup(s, *i);
                 if (r < 0)
@@ -1808,4 +1811,24 @@ int set_put_strdupv(Set *s, char **l) {
 
         return n;
 }
+
+int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags) {
+        const char *p = v;
+        int r;
+
+        assert(s);
+        assert(v);
+
+        for (;;) {
+                char *word;
+
+                r = extract_first_word(&p, &word, separators, flags);
+                if (r <= 0)
+                        return r;
+
+                r = set_consume(s, word);
+                if (r < 0)
+                        return r;
+        }
+}
 #endif // 0
index a510272042fa7f214135fae4552fb0cb29a0cd14..0fda53e111bc81f7d80b4fb67f54c7c95adbd153 100644 (file)
@@ -327,10 +327,12 @@ static inline void *hashmap_first(Hashmap *h) {
 static inline void *ordered_hashmap_first(OrderedHashmap *h) {
         return internal_hashmap_first(HASHMAP_BASE(h));
 }
+
 #if 0 /// UNNEEDED by elogind
 /* no hashmap_next */
 void *ordered_hashmap_next(OrderedHashmap *h, const void *key);
 #endif // 0
+
 char **internal_hashmap_get_strv(HashmapBase *h);
 static inline char **hashmap_get_strv(Hashmap *h) {
         return internal_hashmap_get_strv(HASHMAP_BASE(h));
index 592df53cb56b9cee5e111c31ff0b7ad9092bc92d..c5bda6c4d68db6b69f2ec8a5d996f3928045ee98 100644 (file)
@@ -25,6 +25,7 @@
 #include "alloc-util.h"
 #include "hexdecoct.h"
 #include "macro.h"
+#include "util.h"
 
 char octchar(int x) {
         return '0' + (x & 7);
@@ -275,8 +276,8 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
         if (padding) {
                 /* strip the padding */
                 while (l > 0 && p[l - 1] == '=' && pad < 7) {
-                        pad ++;
-                        l --;
+                        pad++;
+                        l--;
                 }
         }
 
@@ -504,7 +505,7 @@ int unbase64char(char c) {
         if (c == '+')
                 return offset;
 
-        offset ++;
+        offset++;
 
         if (c == '/')
                 return offset;
@@ -572,7 +573,7 @@ static int base64_append_width(char **prefix, int plen,
         if (!t)
                 return -ENOMEM;
 
-        memcpy(t + plen, sep, slen);
+        memcpy_safe(t + plen, sep, slen);
 
         for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
                 int act = MIN(width, avail);
@@ -620,9 +621,9 @@ int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
 
         /* strip the padding */
         if (l > 0 && p[l - 1] == '=')
-                l --;
+                l--;
         if (l > 0 && p[l - 1] == '=')
-                l --;
+                l--;
 
         /* a group of four input bytes needs three output bytes, in case of
            padding we need to add two or three extra bytes */
index b9ab884367d2909b2564a324702690268cda539d..a5cb62eb661e03eaf16682241f82d830ee952e46 100644 (file)
@@ -17,9 +17,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#if defined(__GLIBC__)
-# include <bits/local_lim.h>
-#endif // defined(__GLIBC__)
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
@@ -48,10 +45,15 @@ bool hostname_is_set(void) {
 
         return true;
 }
+#endif // 0
 
 char* gethostname_malloc(void) {
         struct utsname u;
 
+        /* This call tries to return something useful, either the actual hostname
+         * or it makes something up. The only reason it might fail is OOM.
+         * It might even return "localhost" if that's set. */
+
         assert_se(uname(&u) >= 0);
 
         if (isempty(u.nodename) || streq(u.nodename, "(none)"))
@@ -59,6 +61,32 @@ char* gethostname_malloc(void) {
 
         return strdup(u.nodename);
 }
+
+#if 0 /// UNNEEDED by elogind
+int gethostname_strict(char **ret) {
+        struct utsname u;
+        char *k;
+
+        /* This call will rather fail than make up a name. It will not return "localhost" either. */
+
+        assert_se(uname(&u) >= 0);
+
+        if (isempty(u.nodename))
+                return -ENXIO;
+
+        if (streq(u.nodename, "(none)"))
+                return -ENXIO;
+
+        if (is_localhost(u.nodename))
+                return -ENXIO;
+
+        k = strdup(u.nodename);
+        if (!k)
+                return -ENOMEM;
+
+        *ret = k;
+        return 0;
+}
 #endif // 0
 
 static bool hostname_valid_char(char c) {
@@ -100,7 +128,7 @@ bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
                                 return false;
 
                         dot = true;
-                        n_dots ++;
+                        n_dots++;
                 } else {
                         if (!hostname_valid_char(*p))
                                 return false;
@@ -127,6 +155,8 @@ char* hostname_cleanup(char *s) {
 
         assert(s);
 
+        strshorten(s, HOST_NAME_MAX);
+
         for (p = s, d = s, dot = true; *p; p++) {
                 if (*p == '.') {
                         if (dot)
@@ -146,8 +176,6 @@ char* hostname_cleanup(char *s) {
         else
                 *d = 0;
 
-        strshorten(s, HOST_NAME_MAX);
-
         return s;
 }
 #endif // 0
@@ -156,16 +184,16 @@ bool is_localhost(const char *hostname) {
         assert(hostname);
 
         /* This tries to identify local host and domain names
-         * described in RFC6761 plus the redhatism of .localdomain */
+         * described in RFC6761 plus the redhatism of localdomain */
 
         return strcaseeq(hostname, "localhost") ||
                strcaseeq(hostname, "localhost.") ||
-               strcaseeq(hostname, "localdomain.") ||
-               strcaseeq(hostname, "localdomain") ||
+               strcaseeq(hostname, "localhost.localdomain") ||
+               strcaseeq(hostname, "localhost.localdomain.") ||
                endswith_no_case(hostname, ".localhost") ||
                endswith_no_case(hostname, ".localhost.") ||
-               endswith_no_case(hostname, ".localdomain") ||
-               endswith_no_case(hostname, ".localdomain.");
+               endswith_no_case(hostname, ".localhost.localdomain") ||
+               endswith_no_case(hostname, ".localhost.localdomain.");
 }
 
 #if 0 /// UNNEEDED by elogind
index f22716d0ec197113b1d41ab224a8e35225659635..4282d71ae2a98fb6b073e9bdc80a4e85523a730a 100644 (file)
 
 #if 0 /// UNNEEDED by elogind
 bool hostname_is_set(void);
+#endif // 0
 
 char* gethostname_malloc(void);
+#if 0 /// UNNEEDED by elogind
+int gethostname_strict(char **ret);
 #endif // 0
+
 bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_;
 #if 0 /// UNNEEDED by elogind
 char* hostname_cleanup(char *s);
index 3ec8d61236922cb036ed30c7550c893ba7c0f586..cc6dfa8c1b94a29bcaf36cdb139be8dc09467178 100644 (file)
@@ -33,6 +33,11 @@ int flush_fd(int fd) {
                 .events = POLLIN,
         };
 
+        /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
+         * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
+         * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
+         * was set to non-blocking too. */
+
         for (;;) {
                 char buf[LINE_MAX];
                 ssize_t l;
@@ -249,7 +254,7 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
                 } else if (n > 0)
                         q += n;
                 else
-                        q ++;
+                        q++;
         }
 
         if (q > w) {
index 142c940d92692f6a2257aeba0f5786f039e483d2..4684ed3bfc782919b71600521ba7a66f4b04043d 100644 (file)
@@ -46,7 +46,7 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
                 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;
index c68185f5878eaad93d4abba7bb9a1a6107d424cd..5962aa42113b5d425cd181241a7f17da9ef43439 100644 (file)
@@ -32,7 +32,7 @@
 #define LIST_HEAD_INIT(head)                                            \
         do {                                                            \
                 (head) = NULL; }                                        \
-        while(false)
+        while (false)
 
 /* Initialize a list item */
 #define LIST_INIT(name,item)                                            \
@@ -40,7 +40,7 @@
                 typeof(*(item)) *_item = (item);                        \
                 assert(_item);                                          \
                 _item->name##_prev = _item->name##_next = NULL;         \
-        } while(false)
+        } while (false)
 
 /* Prepend an item to the list */
 #define LIST_PREPEND(name,head,item)                                    \
@@ -51,7 +51,7 @@
                         _item->name##_next->name##_prev = _item;        \
                 _item->name##_prev = NULL;                              \
                 *_head = _item;                                         \
-        } while(false)
+        } while (false)
 
 /* Append an item to the list */
 #define LIST_APPEND(name,head,item)                                     \
@@ -59,7 +59,7 @@
                 typeof(*(head)) *_tail;                                 \
                 LIST_FIND_TAIL(name,head,_tail);                        \
                 LIST_INSERT_AFTER(name,head,_tail,item);                \
-        } while(false)
+        } while (false)
 
 /* Remove an item from the list */
 #define LIST_REMOVE(name,head,item)                                     \
@@ -75,7 +75,7 @@
                         *_head = _item->name##_next;                    \
                 }                                                       \
                 _item->name##_next = _item->name##_prev = NULL;         \
-        } while(false)
+        } while (false)
 
 /* Find the head of the list */
 #define LIST_FIND_HEAD(name,item,head)                                  \
                         _b->name##_prev = _a;                           \
                         _a->name##_next = _b;                           \
                 }                                                       \
-        } while(false)
+        } while (false)
 
 /* Insert an item before another one (a = where, b = what) */
 #define LIST_INSERT_BEFORE(name,head,a,b)                               \
                         _b->name##_next = _a;                           \
                         _a->name##_prev = _b;                           \
                 }                                                       \
-        } while(false)
+        } while (false)
 
 #define LIST_JUST_US(name,item)                                         \
         (!(item)->name##_prev && !(item)->name##_next)                  \
index cda6b2895d6497dc237aba91001c8e74f88458d4..ada0a28cd8423d84ec628422a3c9a4622dd83dd3 100644 (file)
@@ -153,6 +153,8 @@ static int add_locales_from_libdir (Set *locales) {
         FOREACH_DIRENT(entry, dir, return -errno) {
                 char *z;
 
+                dirent_ensure_type(dir, entry);
+
                 if (entry->d_type != DT_DIR)
                         continue;
 
@@ -269,34 +271,35 @@ out:
 }
 
 
-const char *draw_special_char(DrawSpecialChar ch) {
-
-        static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
+const char *special_glyph(SpecialGlyph code) {
 
-                /* UTF-8 */ {
-                        [DRAW_TREE_VERTICAL]      = "\342\224\202 ",            /* │  */
-                        [DRAW_TREE_BRANCH]        = "\342\224\234\342\224\200", /* ├─ */
-                        [DRAW_TREE_RIGHT]         = "\342\224\224\342\224\200", /* └─ */
-                        [DRAW_TREE_SPACE]         = "  ",                       /*    */
-                        [DRAW_TRIANGULAR_BULLET]  = "\342\200\243",             /* ‣ */
-                        [DRAW_BLACK_CIRCLE]       = "\342\227\217",             /* ● */
-                        [DRAW_ARROW]              = "\342\206\222",             /* → */
-                        [DRAW_DASH]               = "\342\200\223",             /* – */
+        static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = {
+                /* ASCII fallback */
+                [false] = {
+                        [TREE_VERTICAL]      = "| ",
+                        [TREE_BRANCH]        = "|-",
+                        [TREE_RIGHT]         = "`-",
+                        [TREE_SPACE]         = "  ",
+                        [TRIANGULAR_BULLET]  = ">",
+                        [BLACK_CIRCLE]       = "*",
+                        [ARROW]              = "->",
+                        [MDASH]              = "-",
                 },
 
-                /* ASCII fallback */ {
-                        [DRAW_TREE_VERTICAL]      = "| ",
-                        [DRAW_TREE_BRANCH]        = "|-",
-                        [DRAW_TREE_RIGHT]         = "`-",
-                        [DRAW_TREE_SPACE]         = "  ",
-                        [DRAW_TRIANGULAR_BULLET]  = ">",
-                        [DRAW_BLACK_CIRCLE]       = "*",
-                        [DRAW_ARROW]              = "->",
-                        [DRAW_DASH]               = "-",
-                }
+                /* UTF-8 */
+                [ true ] = {
+                        [TREE_VERTICAL]      = "\342\224\202 ",            /* │  */
+                        [TREE_BRANCH]        = "\342\224\234\342\224\200", /* ├─ */
+                        [TREE_RIGHT]         = "\342\224\224\342\224\200", /* └─ */
+                        [TREE_SPACE]         = "  ",                       /*    */
+                        [TRIANGULAR_BULLET]  = "\342\200\243",             /* ‣ */
+                        [BLACK_CIRCLE]       = "\342\227\217",             /* ● */
+                        [ARROW]              = "\342\206\222",             /* → */
+                        [MDASH]              = "\342\200\223",             /* – */
+                },
         };
 
-        return draw_table[!is_locale_utf8()][ch];
+        return draw_table[is_locale_utf8()][code];
 }
 
 static const char * const locale_variable_table[_VARIABLE_LC_MAX] = {
index b0f9679286c580c0eab994b2ae6040c7ffa5a524..0630a034ab475f48552062c43d9567c9b2a42f7c 100644 (file)
@@ -55,19 +55,19 @@ void init_gettext(void);
 
 bool is_locale_utf8(void);
 
-typedef enum DrawSpecialChar {
-        DRAW_TREE_VERTICAL,
-        DRAW_TREE_BRANCH,
-        DRAW_TREE_RIGHT,
-        DRAW_TREE_SPACE,
-        DRAW_TRIANGULAR_BULLET,
-        DRAW_BLACK_CIRCLE,
-        DRAW_ARROW,
-        DRAW_DASH,
-        _DRAW_SPECIAL_CHAR_MAX
-} DrawSpecialChar;
+typedef enum {
+        TREE_VERTICAL,
+        TREE_BRANCH,
+        TREE_RIGHT,
+        TREE_SPACE,
+        TRIANGULAR_BULLET,
+        BLACK_CIRCLE,
+        ARROW,
+        MDASH,
+        _SPECIAL_GLYPH_MAX
+} SpecialGlyph;
 
-const char *draw_special_char(DrawSpecialChar ch);
+const char *special_glyph(SpecialGlyph code) _const_;
 
 const char* locale_variable_to_string(LocaleVariable i) _const_;
 LocaleVariable locale_variable_from_string(const char *s) _pure_;
index ca12c8b4133c5fdc10be7a84dd360e0e789f123f..da6aa409b5b99b7ebef64f2420627db857fe9b1a 100644 (file)
@@ -71,7 +71,9 @@ static bool syslog_is_stream = false;
 static bool show_color = false;
 static bool show_location = false;
 
-/// UNNEEDED by elogind  static bool upgrade_syslog_to_journal = false;
+#if 0 /// UNNEEDED by elogind
+static bool upgrade_syslog_to_journal = false;
+#endif // 0
 
 /* Akin to glibc's __abort_msg; which is private and we hence cannot
  * use here. */
@@ -165,7 +167,7 @@ static int log_open_syslog(void) {
                 goto fail;
         }
 
-        if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
+        if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
                 safe_close(syslog_fd);
 
                 /* Some legacy syslog systems still use stream
@@ -177,7 +179,7 @@ static int log_open_syslog(void) {
                         goto fail;
                 }
 
-                if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
+                if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
                         r = -errno;
                         goto fail;
                 }
@@ -193,11 +195,13 @@ fail:
         return r;
 }
 
-#if 0 /// UNNEEDED by elogind
 void log_close_journal(void) {
+#if 0 /// elogind does not support journald
         journal_fd = safe_close(journal_fd);
+#endif // 0
 }
 
+#if 0 /// UNNEEDED by elogind
 static int log_open_journal(void) {
 
         static const union sockaddr_union sa = {
@@ -216,7 +220,7 @@ static int log_open_journal(void) {
                 goto fail;
         }
 
-        if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
+        if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
                 r = -errno;
                 goto fail;
         }
@@ -239,7 +243,7 @@ int log_open(void) {
          * because there is no reason to close it. */
 
         if (log_target == LOG_TARGET_NULL) {
-                /// UNNEEDED by elogind log_close_journal();
+                log_close_journal();
                 log_close_syslog();
                 log_close_console();
                 return 0;
@@ -261,11 +265,12 @@ int log_open(void) {
                         }
                 }
 #endif // 0
+
                 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
                     log_target == LOG_TARGET_SYSLOG) {
                         r = log_open_syslog();
                         if (r >= 0) {
-                                /// UNNEEDED by elogind log_close_journal();
+                                log_close_journal();
                                 log_close_console();
                                 return r;
                         }
@@ -273,12 +278,12 @@ int log_open(void) {
 
                 if (log_target == LOG_TARGET_AUTO ||
                     log_target == LOG_TARGET_SAFE ||
-                    /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
+                    log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
                     log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
                     log_target == LOG_TARGET_KMSG) {
                         r = log_open_kmsg();
                         if (r >= 0) {
-                                /// UNNEEDED by elogind log_close_journal();
+                                log_close_journal();
                                 log_close_syslog();
                                 log_close_console();
                                 return r;
@@ -286,7 +291,7 @@ int log_open(void) {
                 }
         }
 
-        /// UNNEEDED by elogind log_close_journal();
+        log_close_journal();
         log_close_syslog();
 
         return log_open_console();
@@ -309,7 +314,7 @@ void log_set_target(LogTarget target) {
 }
 
 void log_close(void) {
-        /// UNNEDED by elogind log_close_journal();
+        log_close_journal();
         log_close_syslog();
         log_close_kmsg();
         log_close_console();
@@ -341,7 +346,7 @@ static int write_to_console(
                 const char *object,
                 const char *buffer) {
 
-        char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2];
+        char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
         struct iovec iovec[6] = {};
         unsigned n = 0;
         bool highlight;
@@ -357,7 +362,7 @@ static int write_to_console(
         highlight = LOG_PRI(level) <= LOG_ERR && show_color;
 
         if (show_location) {
-                xsprintf(location, "(%s:%i) ", file, line);
+                snprintf(location, sizeof(location), "(%s:%i) ", file, line);
                 IOVEC_SET_STRING(iovec[n++], location);
         }
 
@@ -623,7 +628,7 @@ static int log_dispatch(
                     (log_target == LOG_TARGET_AUTO ||
                      log_target == LOG_TARGET_SAFE ||
                      log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
-                     /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
+                     log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
                      log_target == LOG_TARGET_KMSG)) {
 
                         k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
index 42ee76d95ae6b73371b60693f6f30bd92f976d8b..0b82b768c97ac951f2bf96774b76a5242d42051a 100644 (file)
@@ -35,10 +35,8 @@ typedef enum LogTarget{
         LOG_TARGET_CONSOLE,
         LOG_TARGET_CONSOLE_PREFIXED,
         LOG_TARGET_KMSG,
-#if 0 /// elogind does not support logging to systemd-journald
         LOG_TARGET_JOURNAL,
         LOG_TARGET_JOURNAL_OR_KMSG,
-#endif // 0
         LOG_TARGET_SYSLOG,
         LOG_TARGET_SYSLOG_OR_KMSG,
         LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */
@@ -71,10 +69,9 @@ void log_close(void);
 #if 0 /// UNNEEDED by elogind
 void log_forget_fds(void);
 #endif // 0
+
 void log_close_syslog(void);
-#if 0 /// UNNEEDED by elogind
 void log_close_journal(void);
-#endif // 0
 void log_close_kmsg(void);
 void log_close_console(void);
 
@@ -198,13 +195,13 @@ void log_assert_failed_return(
 #ifdef LOG_TRACE
 #  define log_trace(...) log_debug(__VA_ARGS__)
 #else
-#  define log_trace(...) do {} while(0)
+#  define log_trace(...) do {} while (0)
 #endif
 
 #ifdef ENABLE_DEBUG_ELOGIND
 #  define log_debug_elogind(...) log_debug(__VA_ARGS__);usleep(25*USEC_PER_MSEC)
 #else
-#  define log_debug_elogind(...) do {} while(0)
+#  define log_debug_elogind(...) do {} while (0)
 #endif // ENABLE_DEBUG_ELOGIND
 
 /* Structured logging */
@@ -259,5 +256,4 @@ int log_syntax_internal(
                         log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \
                                             "String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \
                 }                                                       \
-                -EINVAL;                                                \
         })
index 89a337d7c1fc1c39c9745268169628b3dcc032ea..b01ee25c884cee292d2d826fc2c7f57a515e5018 100644 (file)
@@ -1,3 +1,5 @@
+#pragma once
+
 /***
   This file is part of systemd.
 
@@ -17,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#pragma once
-
 #include <stdbool.h>
 #include <unistd.h>
 
index 2695d0edb75ba436e645fc1f32786dde78e22bbd..6b2aeb933fdd36bcbcc02cefea06bcc2324322ff 100644 (file)
 #include <inttypes.h>
 #include <stdbool.h>
 #include <sys/param.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 
 #define _printf_(a,b) __attribute__ ((format (printf, a, b)))
-#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
+#ifdef __clang__
+#  define _alloc_(...)
+#else
+#  define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
+#endif
 #define _sentinel_ __attribute__ ((sentinel))
 #define _unused_ __attribute__ ((unused))
 #define _destructor_ __attribute__ ((destructor))
 #define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
 #define UNIQ __COUNTER__
 
+/* builtins */
+#if __SIZEOF_INT__ == 4
+#define BUILTIN_FFS_U32(x) __builtin_ffs(x);
+#elif __SIZEOF_LONG__ == 4
+#define BUILTIN_FFS_U32(x) __builtin_ffsl(x);
+#else
+#error "neither int nor long are four bytes long?!?"
+#endif
+
 /* Rounds up */
 
 #define ALIGN4(l) (((l) + 3) & ~3)
@@ -224,7 +238,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
 /* We override the glibc assert() here. */
 #undef assert
 #ifdef NDEBUG
-#define assert(expr) do {} while(false)
+#define assert(expr) do {} while (false)
 #else
 #define assert(expr) assert_message_se(expr, #expr)
 #endif
@@ -361,6 +375,12 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
                 _found;                         \
         })
 
+#define SWAP_TWO(x, y) do {                        \
+                typeof(x) _t = (x);                \
+                (x) = (y);                         \
+                (y) = (_t);                        \
+        } while (false)
+
 /* Define C11 thread_local attribute even on older gcc compiler
  * version */
 #ifndef thread_local
index 66b5e5c7b932b845218cacf778aa941bde624eb3..e857c040d8657db9fa8ed831e16e5f53b512a7f7 100644 (file)
@@ -22,7 +22,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #ifdef HAVE_LINUX_MEMFD_H
-#  include <linux/memfd.h>
+#include <linux/memfd.h>
 #endif
 #include <stdio.h>
 #include <sys/mman.h>
index 419d8997939f9141cfa2a464778e20de8fa34fe2..6b828520e8258a0d771e875cf16e3ca3731dd811 100644 (file)
@@ -30,6 +30,7 @@ int memfd_new_and_map(const char *name, size_t sz, void **p);
 
 int memfd_map(int fd, uint64_t offset, size_t size, void **p);
 #endif // 0
+
 int memfd_set_sealed(int fd);
 #if 0 /// UNNEEDED by elogind
 int memfd_get_sealed(int fd);
index fea7841bcff8ebe0fd097f6869bfaf59088b39db..0618b8dd223c8b7de0fcb2b88545aaa7844b7b69 100644 (file)
@@ -36,7 +36,7 @@ void* mempool_alloc0_tile(struct mempool *mp);
 void mempool_free_tile(struct mempool *mp, void *p);
 
 #define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \
-struct mempool pool_name = { \
+static struct mempool pool_name = { \
         .tile_size = sizeof(tile_type), \
         .at_least = alloc_at_least, \
 }
index f2bc828dd2f00b6e5bc937493b4d882f87cfbab3..f2a0e1d8b0402605ace33e5a68db283e353e5948 100644 (file)
 #include <linux/neighbour.h>
 #include <linux/oom.h>
 #include <linux/rtnetlink.h>
+#include <net/ethernet.h>
 #include <stdlib.h>
 #include <sys/resource.h>
 #include <sys/syscall.h>
 #include <uchar.h>
 #include <unistd.h>
 
+/// Additional includes needed by elogind
 #include "musl_missing.h"
 
 #ifdef HAVE_AUDIT
 #define SOL_SCTP 132
 #endif
 
-#if !HAVE_DECL_PIVOT_ROOT
-static inline int pivot_root(const char *new_root, const char *put_old) {
-        return syscall(SYS_pivot_root, new_root, put_old);
-}
-#endif
-
-#ifndef __NR_memfd_create
-#  if defined __x86_64__
-#    define __NR_memfd_create 319
-#  elif defined __arm__
-#    define __NR_memfd_create 385
-#  elif defined __aarch64__
-#    define __NR_memfd_create 279
-#  elif defined __s390__
-#    define __NR_memfd_create 350
-#  elif defined _MIPS_SIM
-#    if _MIPS_SIM == _MIPS_SIM_ABI32
-#      define __NR_memfd_create 4354
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_NABI32
-#      define __NR_memfd_create 6318
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_ABI64
-#      define __NR_memfd_create 5314
-#    endif
-#  elif defined __i386__
-#    define __NR_memfd_create 356
-#  else
-#    warning "__NR_memfd_create unknown for your architecture"
-#    define __NR_memfd_create 0xffffffff
-#  endif
-#endif
-
-#ifndef HAVE_MEMFD_CREATE
-static inline int memfd_create(const char *name, unsigned int flags) {
-        return syscall(__NR_memfd_create, name, flags);
-}
-#endif
-
-#ifndef __NR_getrandom
-#  if defined __x86_64__
-#    define __NR_getrandom 318
-#  elif defined(__i386__)
-#    define __NR_getrandom 355
-#  elif defined(__arm__)
-#    define __NR_getrandom 384
-# elif defined(__aarch64__)
-#    define __NR_getrandom 278
-#  elif defined(__ia64__)
-#    define __NR_getrandom 1339
-#  elif defined(__m68k__)
-#    define __NR_getrandom 352
-#  elif defined(__s390x__)
-#    define __NR_getrandom 349
-#  elif defined(__powerpc__)
-#    define __NR_getrandom 359
-#  elif defined _MIPS_SIM
-#    if _MIPS_SIM == _MIPS_SIM_ABI32
-#      define __NR_getrandom 4353
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_NABI32
-#      define __NR_getrandom 6317
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_ABI64
-#      define __NR_getrandom 5313
-#    endif
-#  else
-#    warning "__NR_getrandom unknown for your architecture"
-#    define __NR_getrandom 0xffffffff
-#  endif
-#endif
-
-#if !HAVE_DECL_GETRANDOM
-static inline int getrandom(void *buffer, size_t count, unsigned flags) {
-        return syscall(__NR_getrandom, buffer, count, flags);
-}
-#endif
-
 #ifndef GRND_NONBLOCK
 #define GRND_NONBLOCK 0x0001
 #endif
@@ -469,6 +393,10 @@ struct btrfs_ioctl_quota_ctl_args {
                                struct btrfs_ioctl_qgroup_limit_args)
 #endif
 
+#ifndef BTRFS_IOC_QUOTA_RESCAN_WAIT
+#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46)
+#endif
+
 #ifndef BTRFS_FIRST_FREE_OBJECTID
 #define BTRFS_FIRST_FREE_OBJECTID 256
 #endif
@@ -514,15 +442,34 @@ struct btrfs_ioctl_quota_ctl_args {
 #endif
 
 #endif // 0
-
 #ifndef CGROUP_SUPER_MAGIC
 #define CGROUP_SUPER_MAGIC 0x27e0eb
 #endif
 
+#ifndef CGROUP2_SUPER_MAGIC
+#define CGROUP2_SUPER_MAGIC 0x63677270
+#endif
+
 #ifndef TMPFS_MAGIC
 #define TMPFS_MAGIC 0x01021994
 #endif
 
+#ifndef MQUEUE_MAGIC
+#define MQUEUE_MAGIC 0x19800202
+#endif
+
+#ifndef SECURITYFS_MAGIC
+#define SECURITYFS_MAGIC 0x73636673
+#endif
+
+#ifndef TRACEFS_MAGIC
+#define TRACEFS_MAGIC 0x74726163
+#endif
+
+#ifndef BPF_FS_MAGIC
+#define BPF_FS_MAGIC 0xcafe4a11
+#endif
+
 #ifndef MS_MOVE
 #define MS_MOVE 8192
 #endif
@@ -531,12 +478,6 @@ struct btrfs_ioctl_quota_ctl_args {
 #define MS_PRIVATE  (1 << 18)
 #endif
 
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
-        return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
 #ifndef SCM_SECURITY
 #define SCM_SECURITY 0x03
 #endif
@@ -565,32 +506,6 @@ static inline pid_t gettid(void) {
 #define MAX_HANDLE_SZ 128
 #endif
 
-#ifndef __NR_name_to_handle_at
-#  if defined(__x86_64__)
-#    define __NR_name_to_handle_at 303
-#  elif defined(__i386__)
-#    define __NR_name_to_handle_at 341
-#  elif defined(__arm__)
-#    define __NR_name_to_handle_at 370
-#  elif defined(__powerpc__)
-#    define __NR_name_to_handle_at 345
-#  else
-#    error "__NR_name_to_handle_at is not defined"
-#  endif
-#endif
-
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
-struct file_handle {
-        unsigned int handle_bytes;
-        int handle_type;
-        unsigned char f_handle[0];
-};
-
-static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
-        return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
-}
-#endif
-
 #ifndef HAVE_SECURE_GETENV
 #  ifdef HAVE___SECURE_GETENV
 #    define secure_getenv __secure_getenv
@@ -639,22 +554,6 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
 
 #endif
 
-#ifndef __NR_setns
-#  if defined(__x86_64__)
-#    define __NR_setns 308
-#  elif defined(__i386__)
-#    define __NR_setns 346
-#  else
-#    error "__NR_setns is not defined"
-#  endif
-#endif
-
-#if !HAVE_DECL_SETNS
-static inline int setns(int fd, int nstype) {
-        return syscall(__NR_setns, fd, nstype);
-}
-#endif
-
 #if !HAVE_DECL_LO_FLAGS_PARTSCAN
 #define LO_FLAGS_PARTSCAN 8
 #endif
@@ -679,12 +578,16 @@ static inline int setns(int fd, int nstype) {
 #define IFLA_INET6_ADDR_GEN_MODE 8
 #define __IFLA_INET6_MAX 9
 
-#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
+#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
 
 #define IN6_ADDR_GEN_MODE_EUI64 0
 #define IN6_ADDR_GEN_MODE_NONE 1
 #endif
 
+#if !HAVE_DECL_IN6_ADDR_GEN_MODE_STABLE_PRIVACY
+#define IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2
+#endif
+
 #if !HAVE_DECL_IFLA_MACVLAN_FLAGS
 #define IFLA_MACVLAN_UNSPEC 0
 #define IFLA_MACVLAN_MODE 1
@@ -719,6 +622,7 @@ static inline int setns(int fd, int nstype) {
 #endif
 
 #if !HAVE_DECL_IFLA_PHYS_PORT_ID
+#define IFLA_EXT_MASK 29
 #undef IFLA_PROMISCUITY
 #define IFLA_PROMISCUITY 30
 #define IFLA_NUM_TX_QUEUES 31
@@ -863,7 +767,15 @@ static inline int setns(int fd, int nstype) {
 #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
 #endif
 
-#if !HAVE_DECL_IFLA_BR_PRIORITY
+#ifndef BRIDGE_VLAN_INFO_RANGE_BEGIN
+#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */
+#endif
+
+#ifndef BRIDGE_VLAN_INFO_RANGE_END
+#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */
+#endif
+
+#if !HAVE_DECL_IFLA_BR_VLAN_DEFAULT_PVID
 #define IFLA_BR_UNSPEC 0
 #define IFLA_BR_FORWARD_DELAY 1
 #define IFLA_BR_HELLO_TIME 2
@@ -871,7 +783,40 @@ static inline int setns(int fd, int nstype) {
 #define IFLA_BR_AGEING_TIME 4
 #define IFLA_BR_STP_STATE 5
 #define IFLA_BR_PRIORITY 6
-#define __IFLA_BR_MAX 7
+#define IFLA_BR_VLAN_FILTERING 7
+#define IFLA_BR_VLAN_PROTOCOL 8
+#define IFLA_BR_GROUP_FWD_MASK 9
+#define IFLA_BR_ROOT_ID 10
+#define IFLA_BR_BRIDGE_ID 11
+#define IFLA_BR_ROOT_PORT 12
+#define IFLA_BR_ROOT_PATH_COST 13
+#define IFLA_BR_TOPOLOGY_CHANGE 14
+#define IFLA_BR_TOPOLOGY_CHANGE_DETECTED 15
+#define IFLA_BR_HELLO_TIMER 16
+#define IFLA_BR_TCN_TIMER 17
+#define IFLA_BR_TOPOLOGY_CHANGE_TIMER 18
+#define IFLA_BR_GC_TIMER 19
+#define IFLA_BR_GROUP_ADDR 20
+#define IFLA_BR_FDB_FLUSH 21
+#define IFLA_BR_MCAST_ROUTER 22
+#define IFLA_BR_MCAST_SNOOPING 23
+#define IFLA_BR_MCAST_QUERY_USE_IFADDR 24
+#define IFLA_BR_MCAST_QUERIER 25
+#define IFLA_BR_MCAST_HASH_ELASTICITY 26
+#define IFLA_BR_MCAST_HASH_MAX 27
+#define IFLA_BR_MCAST_LAST_MEMBER_CNT 28
+#define IFLA_BR_MCAST_STARTUP_QUERY_CNT 29
+#define IFLA_BR_MCAST_LAST_MEMBER_INTVL 30
+#define IFLA_BR_MCAST_MEMBERSHIP_INTVL 31
+#define IFLA_BR_MCAST_QUERIER_INTVL 32
+#define IFLA_BR_MCAST_QUERY_INTVL 33
+#define IFLA_BR_MCAST_QUERY_RESPONSE_INTVL 34
+#define IFLA_BR_MCAST_STARTUP_QUERY_INTVL 35
+#define IFLA_BR_NF_CALL_IPTABLES 36
+#define IFLA_BR_NF_CALL_IP6TABLES 37
+#define IFLA_BR_NF_CALL_ARPTABLES 38
+#define IFLA_BR_VLAN_DEFAULT_PVID 39
+#define __IFLA_BR_MAX 40
 
 #define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
 #endif
@@ -887,13 +832,20 @@ static inline int setns(int fd, int nstype) {
 #define IFLA_BRPORT_FAST_LEAVE 7
 #define IFLA_BRPORT_LEARNING 8
 #define IFLA_BRPORT_UNICAST_FLOOD 9
-#define IFLA_BRPORT_PROXYARP 10
 #define IFLA_BRPORT_LEARNING_SYNC 11
 #define __IFLA_BRPORT_MAX 12
 
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
 #endif
 
+#if !HAVE_DECL_IFLA_BRPORT_PROXYARP
+#define IFLA_BRPORT_PROXYARP 10
+#endif
+
+#if !HAVE_DECL_IFLA_VRF_TABLE
+#define IFLA_VRF_TABLE 1
+#endif
+
 #if !HAVE_DECL_NDA_IFINDEX
 #define NDA_UNSPEC 0
 #define NDA_DST 1
@@ -917,6 +869,10 @@ static inline int setns(int fd, int nstype) {
 #define IPV6_UNICAST_IF 76
 #endif
 
+#ifndef IPV6_MIN_MTU
+#define IPV6_MIN_MTU 1280
+#endif
+
 #ifndef IFF_MULTI_QUEUE
 #define IFF_MULTI_QUEUE 0x100
 #endif
@@ -1018,72 +974,11 @@ static inline int setns(int fd, int nstype) {
 #define CAP_AUDIT_READ 37
 #endif
 
-static inline int raw_clone(unsigned long flags, void *child_stack) {
-#if defined(__s390__) || defined(__CRIS__)
-        /* On s390 and cris the order of the first and second arguments
-         * of the raw clone() system call is reversed. */
-        return (int) syscall(__NR_clone, child_stack, flags);
-#else
-        return (int) syscall(__NR_clone, flags, child_stack);
-#endif
-}
-
-static inline pid_t raw_getpid(void) {
-#if defined(__alpha__)
-        return (pid_t) syscall(__NR_getxpid);
-#else
-        return (pid_t) syscall(__NR_getpid);
-#endif
-}
-
 #if 0 /// UNNEEDED by elogind
-
-#if !HAVE_DECL_RENAMEAT2
-
-
-#ifndef __NR_renameat2
-#  if defined __x86_64__
-#    define __NR_renameat2 316
-#  elif defined __arm__
-#    define __NR_renameat2 382
-#  elif defined _MIPS_SIM
-#    if _MIPS_SIM == _MIPS_SIM_ABI32
-#      define __NR_renameat2 4351
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_NABI32
-#      define __NR_renameat2 6315
-#    endif
-#    if _MIPS_SIM == _MIPS_SIM_ABI64
-#      define __NR_renameat2 5311
-#    endif
-#  elif defined __i386__
-#    define __NR_renameat2 353
-#  else
-#    warning "__NR_renameat2 unknown for your architecture"
-#    define __NR_renameat2 0xffffffff
-#  endif
-#endif
-
-static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
-        return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
-}
-#endif
-
 #ifndef RENAME_NOREPLACE
 #define RENAME_NOREPLACE (1 << 0)
 #endif
 
-#if !HAVE_DECL_KCMP
-static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
-#if defined(__NR_kcmp)
-        return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-#endif
-
 #ifndef KCMP_FILE
 #define KCMP_FILE 0
 #endif
@@ -1095,40 +990,13 @@ static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, uns
 #ifndef INPUT_PROP_ACCELEROMETER
 #define INPUT_PROP_ACCELEROMETER  0x06
 #endif
+#endif // 0
 
-#if !HAVE_DECL_KEY_SERIAL_T
+#ifndef HAVE_KEY_SERIAL_T
 typedef int32_t key_serial_t;
 #endif
 
-#if !HAVE_DECL_KEYCTL
-static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
-#if defined(__NR_keyctl)
-        return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-
-static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
-#if defined (__NR_add_key)
-        return syscall(__NR_add_key, type, description, payload, plen, ringid);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-
-static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
-#if defined (__NR_request_key)
-        return syscall(__NR_request_key, type, description, callout_info, destringid);
-#else
-        errno = ENOSYS;
-        return -1;
-#endif
-}
-#endif
-
+#if 0 /// UNNEEDED by elogind
 #ifndef KEYCTL_READ
 #define KEYCTL_READ 11
 #endif
@@ -1168,12 +1036,18 @@ static inline key_serial_t request_key(const char *type, const char *description
 #ifndef IF_OPER_UP
 #define IF_OPER_UP 6
 
-#ifndef HAVE_DECL_CHAR32_T
+#ifndef HAVE_CHAR32_T
 #define char32_t uint32_t
 #endif
 
-#ifndef HAVE_DECL_CHAR16_T
+#ifndef HAVE_CHAR16_T
 #define char16_t uint16_t
 #endif
 
+#ifndef ETHERTYPE_LLDP
+#define ETHERTYPE_LLDP 0x88cc
+#endif
+
 #endif
+
+#include "missing_syscall.h"
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
new file mode 100644 (file)
index 0000000..84598c0
--- /dev/null
@@ -0,0 +1,304 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2016 Zbigniew Jędrzejewski-Szmek
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+/* Missing glibc definitions to access certain kernel APIs */
+
+#if 0 /// UNNEEDED by elogind
+#if !HAVE_DECL_PIVOT_ROOT
+static inline int pivot_root(const char *new_root, const char *put_old) {
+        return syscall(SYS_pivot_root, new_root, put_old);
+}
+#endif
+#endif // 0
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_MEMFD_CREATE
+#  ifndef __NR_memfd_create
+#    if defined __x86_64__
+#      define __NR_memfd_create 319
+#    elif defined __arm__
+#      define __NR_memfd_create 385
+#    elif defined __aarch64__
+#      define __NR_memfd_create 279
+#    elif defined __s390__
+#      define __NR_memfd_create 350
+#    elif defined _MIPS_SIM
+#      if _MIPS_SIM == _MIPS_SIM_ABI32
+#        define __NR_memfd_create 4354
+#      endif
+#      if _MIPS_SIM == _MIPS_SIM_NABI32
+#        define __NR_memfd_create 6318
+#      endif
+#      if _MIPS_SIM == _MIPS_SIM_ABI64
+#        define __NR_memfd_create 5314
+#      endif
+#    elif defined __i386__
+#      define __NR_memfd_create 356
+#    else
+#      warning "__NR_memfd_create unknown for your architecture"
+#    endif
+#  endif
+
+static inline int memfd_create(const char *name, unsigned int flags) {
+#  ifdef __NR_memfd_create
+        return syscall(__NR_memfd_create, name, flags);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_GETRANDOM
+#  ifndef __NR_getrandom
+#    if defined __x86_64__
+#      define __NR_getrandom 318
+#    elif defined(__i386__)
+#      define __NR_getrandom 355
+#    elif defined(__arm__)
+#      define __NR_getrandom 384
+#   elif defined(__aarch64__)
+#      define __NR_getrandom 278
+#    elif defined(__ia64__)
+#      define __NR_getrandom 1339
+#    elif defined(__m68k__)
+#      define __NR_getrandom 352
+#    elif defined(__s390x__)
+#      define __NR_getrandom 349
+#    elif defined(__powerpc__)
+#      define __NR_getrandom 359
+#    elif defined _MIPS_SIM
+#      if _MIPS_SIM == _MIPS_SIM_ABI32
+#        define __NR_getrandom 4353
+#      endif
+#      if _MIPS_SIM == _MIPS_SIM_NABI32
+#        define __NR_getrandom 6317
+#      endif
+#      if _MIPS_SIM == _MIPS_SIM_ABI64
+#        define __NR_getrandom 5313
+#      endif
+#    else
+#      warning "__NR_getrandom unknown for your architecture"
+#    endif
+#  endif
+
+static inline int getrandom(void *buffer, size_t count, unsigned flags) {
+#  ifdef __NR_getrandom
+        return syscall(__NR_getrandom, buffer, count, flags);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_GETTID
+static inline pid_t gettid(void) {
+        return (pid_t) syscall(SYS_gettid);
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_NAME_TO_HANDLE_AT
+#  ifndef __NR_name_to_handle_at
+#    if defined(__x86_64__)
+#      define __NR_name_to_handle_at 303
+#    elif defined(__i386__)
+#      define __NR_name_to_handle_at 341
+#    elif defined(__arm__)
+#      define __NR_name_to_handle_at 370
+#    elif defined(__powerpc__)
+#      define __NR_name_to_handle_at 345
+#    else
+#      error "__NR_name_to_handle_at is not defined"
+#    endif
+#  endif
+
+struct file_handle {
+        unsigned int handle_bytes;
+        int handle_type;
+        unsigned char f_handle[0];
+};
+
+static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
+#  ifdef __NR_name_to_handle_at
+        return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_SETNS
+#  ifndef __NR_setns
+#    if defined(__x86_64__)
+#      define __NR_setns 308
+#    elif defined(__i386__)
+#      define __NR_setns 346
+#    else
+#      error "__NR_setns is not defined"
+#    endif
+#  endif
+
+static inline int setns(int fd, int nstype) {
+#  ifdef __NR_setns
+        return syscall(__NR_setns, fd, nstype);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if 0 /// UNNEEDED by elogind
+static inline pid_t raw_getpid(void) {
+#if defined(__alpha__)
+        return (pid_t) syscall(__NR_getxpid);
+#else
+        return (pid_t) syscall(__NR_getpid);
+#endif
+}
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_RENAMEAT2
+#  ifndef __NR_renameat2
+#    if defined __x86_64__
+#      define __NR_renameat2 316
+#    elif defined __arm__
+#      define __NR_renameat2 382
+#    elif defined _MIPS_SIM
+#      if _MIPS_SIM == _MIPS_SIM_ABI32
+#        define __NR_renameat2 4351
+#      endif
+#      if _MIPS_SIM == _MIPS_SIM_NABI32
+#        define __NR_renameat2 6315
+#      endif
+#      if _MIPS_SIM == _MIPS_SIM_ABI64
+#        define __NR_renameat2 5311
+#      endif
+#    elif defined __i386__
+#      define __NR_renameat2 353
+#    else
+#      warning "__NR_renameat2 unknown for your architecture"
+#    endif
+#  endif
+
+static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
+#  ifdef __NR_renameat2
+        return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_KCMP
+static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
+#  ifdef __NR_kcmp
+        return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_KEYCTL
+static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
+#  ifdef __NR_keyctl
+        return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+
+static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
+#  ifdef __NR_add_key
+        return syscall(__NR_add_key, type, description, payload, plen, ringid);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+
+static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
+#  ifdef __NR_request_key
+        return syscall(__NR_request_key, type, description, callout_info, destringid);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+#endif
+#endif // 0
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_COPY_FILE_RANGE
+#  ifndef __NR_copy_file_range
+#    if defined(__x86_64__)
+#      define __NR_copy_file_range 326
+#    elif defined(__i386__)
+#      define __NR_copy_file_range 377
+#    elif defined __s390__
+#      define __NR_copy_file_range 375
+#    elif defined __arm__
+#      define __NR_copy_file_range 391
+#    elif defined __aarch64__
+#      define __NR_copy_file_range 285
+#    elif defined __powerpc__
+#      define __NR_copy_file_range 379
+#    else
+#      warning "__NR_copy_file_range not defined for your architecture"
+#    endif
+#  endif
+
+static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
+                                      int fd_out, loff_t *off_out,
+                                      size_t len,
+                                      unsigned int flags) {
+#  ifdef __NR_copy_file_range
+        return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+#endif
index 62e9b082e2015053fb22bacaebc398a0f0b4c82a..db1e8329135784309bbf60ac91e4507667ca2b61 100644 (file)
 
 #include "fs-util.h"
 #include "macro.h"
-#include "missing.h"
 #include "mkdir.h"
 #include "path-util.h"
 #include "stat-util.h"
 #include "user-util.h"
 
+/// Additional includes needed by elogind
+#include "missing.h"
+
 int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) {
         struct stat st;
 
index da34ef6e71a7d1c3cd33012f68e6727c4ef652ec..121619eed08d844c11e19fbb59b3954f1a05493d 100644 (file)
@@ -47,7 +47,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
         if ((flags & AT_EMPTY_PATH) && isempty(filename))
                 xsprintf(path, "/proc/self/fdinfo/%i", fd);
         else {
-                subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
+                subfd = openat(fd, filename, O_CLOEXEC|O_PATH);
                 if (subfd < 0)
                         return -errno;
 
@@ -104,7 +104,7 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
          *
          * As last fallback we do traditional fstat() based st_dev
          * comparisons. This is how things were traditionally done,
-         * but unionfs breaks breaks this since it exposes file
+         * but unionfs breaks this since it exposes file
          * systems with a variety of st_dev reported. Also, btrfs
          * subvolumes have different st_dev, even though they aren't
          * real mounts of their own. */
@@ -230,7 +230,7 @@ int path_is_mount_point(const char *t, int flags) {
         if (!parent)
                 return -ENOMEM;
 
-        fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
+        fd = openat(AT_FDCWD, parent, O_DIRECTORY|O_CLOEXEC|O_PATH);
         if (fd < 0)
                 return -errno;
 
@@ -449,21 +449,21 @@ int bind_remount_recursive(const char *prefix, bool ro) {
                         if (r < 0)
                                 return r;
 
-                        /* Try to reuse the original flag set, but
-                         * don't care for errors, in case of
-                         * obstructed mounts */
+                        /* Deal with mount points that are obstructed by a
+                         * later mount */
+                        r = path_is_mount_point(x, 0);
+                        if (r == -ENOENT || r == 0)
+                                continue;
+                        if (r < 0)
+                                return r;
+
+                        /* Try to reuse the original flag set */
                         orig_flags = 0;
                         (void) get_mount_flags(x, &orig_flags);
                         orig_flags &= ~MS_RDONLY;
 
-                        if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
-
-                                /* Deal with mount points that are
-                                 * obstructed by a later mount */
-
-                                if (errno != ENOENT)
-                                        return -errno;
-                        }
+                        if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
+                                return -errno;
 
                 }
         }
@@ -499,7 +499,10 @@ bool fstype_is_network(const char *fstype) {
                 "nfs4\0"
                 "gfs\0"
                 "gfs2\0"
-                "glusterfs\0";
+                "glusterfs\0"
+                "pvfs2\0" /* OrangeFS */
+                "ocfs2\0"
+                ;
 
         const char *x;
 
@@ -531,3 +534,28 @@ int repeat_unmount(const char *path, int flags) {
         }
 }
 #endif // 0
+
+const char* mode_to_inaccessible_node(mode_t mode) {
+        /* This function maps a node type to the correspondent inaccessible node type.
+         * Character and block inaccessible devices may not be created (because major=0 and minor=0),
+         * in such case we map character and block devices to the inaccessible node type socket. */
+        switch(mode & S_IFMT) {
+                case S_IFREG:
+                        return "/run/systemd/inaccessible/reg";
+                case S_IFDIR:
+                        return "/run/systemd/inaccessible/dir";
+                case S_IFCHR:
+                        if (access("/run/systemd/inaccessible/chr", F_OK) == 0)
+                                return "/run/systemd/inaccessible/chr";
+                        return "/run/systemd/inaccessible/sock";
+                case S_IFBLK:
+                        if (access("/run/systemd/inaccessible/blk", F_OK) == 0)
+                                return "/run/systemd/inaccessible/blk";
+                        return "/run/systemd/inaccessible/sock";
+                case S_IFIFO:
+                        return "/run/systemd/inaccessible/fifo";
+                case S_IFSOCK:
+                        return "/run/systemd/inaccessible/sock";
+        }
+        return NULL;
+}
index 237bd4711204a2f0ca02f28800c08de063ed7663..9ed5b284ceab5e275c02a1ac30b9c49b8accd02e 100644 (file)
@@ -53,4 +53,6 @@ union file_handle_union {
         char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ];
 };
 
+const char* mode_to_inaccessible_node(mode_t mode);
+
 #define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ }
index 29012b837638b059dc8bb533a9da0c732b612382..77e85f658a9a23f16cb63e72496739631076d7aa 100644 (file)
@@ -23,7 +23,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-//#include <xlocale.h>
+#if defined(__GLIBC__)
+#  include <xlocale.h>
+#endif // defined(__GLIBC__)
 
 #include "alloc-util.h"
 //#include "extract-word.h"
@@ -31,6 +33,9 @@
 #include "parse-util.h"
 #include "string-util.h"
 
+/// Additional includes needed by elogind
+#include "musl_missing.h"
+
 int parse_boolean(const char *v) {
         assert(v);
 
@@ -507,7 +512,7 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
         s = *p;
 
         /* accept any number of digits, strtoull is limted to 19 */
-        for(i=0; i < digits; i++,s++) {
+        for (i=0; i < digits; i++,s++) {
                 if (*s < '0' || *s > '9') {
                         if (i == 0)
                                 return -EINVAL;
@@ -534,3 +539,22 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
 
         return 0;
 }
+
+int parse_percent(const char *p) {
+        const char *pc, *n;
+        unsigned v;
+        int r;
+
+        pc = endswith(p, "%");
+        if (!pc)
+                return -EINVAL;
+
+        n = strndupa(p, pc - p);
+        r = safe_atou(n, &v);
+        if (r < 0)
+                return r;
+        if (v > 100)
+                return -ERANGE;
+
+        return (int) v;
+}
index 49184ecc38f4e34ba7db090cafe8e91639899c1d..1f420c050b9906ba137b440a986be3b405facb11 100644 (file)
@@ -35,7 +35,6 @@ int parse_mode(const char *s, mode_t *ret);
 int parse_ifindex(const char *s, int *ret);
 
 int parse_size(const char *t, uint64_t base, uint64_t *size);
-
 #if 0 /// UNNEEDED by elogind
 int parse_range(const char *t, unsigned *lower, unsigned *upper);
 
@@ -93,6 +92,20 @@ static inline int safe_atoli(const char *s, long int *ret_u) {
 }
 #endif
 
+#if SIZE_MAX == UINT_MAX
+static inline int safe_atozu(const char *s, size_t *ret_u) {
+        assert_cc(sizeof(size_t) == sizeof(unsigned));
+        return safe_atou(s, (unsigned *) ret_u);
+}
+#else
+static inline int safe_atozu(const char *s, size_t *ret_u) {
+        assert_cc(sizeof(size_t) == sizeof(long unsigned));
+        return safe_atolu(s, ret_u);
+}
+#endif
+
 int safe_atod(const char *s, double *ret_d);
 
 int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
+
+int parse_percent(const char *p);
index b222146c73f49f0fa2212c19939ffcfdbdd209ae..123b4ce8c89e8db5f58660c31581b33667004a60 100644 (file)
@@ -100,9 +100,9 @@ int path_make_absolute_cwd(const char *p, char **ret) {
         else {
                 _cleanup_free_ char *cwd = NULL;
 
-        cwd = get_current_dir_name();
-        if (!cwd)
-                        return -errno;
+                cwd = get_current_dir_name();
+                if (!cwd)
+                        return negative_errno();
 
                 c = strjoin(cwd, "/", p, NULL);
         }
@@ -477,10 +477,10 @@ int find_binary(const char *name, char **ret) {
                 return 0;
         }
 
-                /**
-                 * Plain getenv, not secure_getenv, because we want
-                 * to actually allow the user to pick the binary.
-                 */
+        /**
+         * Plain getenv, not secure_getenv, because we want
+         * to actually allow the user to pick the binary.
+         */
         p = getenv("PATH");
         if (!p)
                 p = DEFAULT_PATH;
@@ -497,7 +497,7 @@ int find_binary(const char *name, char **ret) {
                         break;
 
                 if (!path_is_absolute(element))
-                                continue;
+                        continue;
 
                 j = strjoin(element, "/", name, NULL);
                 if (!j)
@@ -574,10 +574,10 @@ static int binary_is_good(const char *binary) {
         if (r < 0)
                 return r;
 
-        return !path_equal(d, "true") &&
-               !path_equal(d, "/bin/true") &&
-               !path_equal(d, "/usr/bin/true") &&
-               !path_equal(d, "/dev/null");
+        return !PATH_IN_SET(d, "true"
+                               "/bin/true",
+                               "/usr/bin/true",
+                               "/dev/null");
 }
 
 int fsck_exists(const char *fstype) {
@@ -762,34 +762,53 @@ char *file_in_same_dir(const char *path, const char *filename) {
         return ret;
 }
 
-bool hidden_file_allow_backup(const char *filename) {
-        assert(filename);
-
-        return
-                filename[0] == '.' ||
-                streq(filename, "lost+found") ||
-                streq(filename, "aquota.user") ||
-                streq(filename, "aquota.group") ||
-                endswith(filename, ".rpmnew") ||
-                endswith(filename, ".rpmsave") ||
-                endswith(filename, ".rpmorig") ||
-                endswith(filename, ".dpkg-old") ||
-                endswith(filename, ".dpkg-new") ||
-                endswith(filename, ".dpkg-tmp") ||
-                endswith(filename, ".dpkg-dist") ||
-                endswith(filename, ".dpkg-bak") ||
-                endswith(filename, ".dpkg-backup") ||
-                endswith(filename, ".dpkg-remove") ||
-                endswith(filename, ".swp");
-}
+bool hidden_or_backup_file(const char *filename) {
+        const char *p;
 
-bool hidden_file(const char *filename) {
         assert(filename);
 
-        if (endswith(filename, "~"))
+        if (filename[0] == '.' ||
+            streq(filename, "lost+found") ||
+            streq(filename, "aquota.user") ||
+            streq(filename, "aquota.group") ||
+            endswith(filename, "~"))
                 return true;
 
-        return hidden_file_allow_backup(filename);
+        p = strrchr(filename, '.');
+        if (!p)
+                return false;
+
+        /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up
+         * with always new suffixes and that everybody else should just adjust to that, then it really should be on
+         * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt
+         * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional
+         * string. Specifically: there's now:
+         *
+         *    The generic suffixes "~" and ".bak" for backup files
+         *    The generic prefix "." for hidden files
+         *
+         * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist"
+         * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead.
+         */
+
+        return STR_IN_SET(p + 1,
+                          "rpmnew",
+                          "rpmsave",
+                          "rpmorig",
+                          "dpkg-old",
+                          "dpkg-new",
+                          "dpkg-tmp",
+                          "dpkg-dist",
+                          "dpkg-bak",
+                          "dpkg-backup",
+                          "dpkg-remove",
+                          "ucf-new",
+                          "ucf-old",
+                          "ucf-dist",
+                          "swp",
+                          "bak",
+                          "old",
+                          "new");
 }
 
 #if 0 /// UNNEEDED by elogind
index 99035aae9578583fb84de04811020c9b57ecd410..540a69c62754518c938be0492cb7d1157429540c 100644 (file)
@@ -55,6 +55,25 @@ bool path_equal_or_files_same(const char *a, const char *b);
 #if 0 /// UNNEEDED by elogind
 char* path_join(const char *root, const char *path, const char *rest);
 
+static inline bool path_equal_ptr(const char *a, const char *b) {
+        return !!a == !!b && (!a || path_equal(a, b));
+}
+#endif // 0
+
+/* Note: the search terminates on the first NULL item. */
+#define PATH_IN_SET(p, ...)                                     \
+        ({                                                      \
+                char **s;                                       \
+                bool _found = false;                            \
+                STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__))         \
+                        if (path_equal(p, *s)) {                \
+                               _found = true;                   \
+                               break;                           \
+                        }                                       \
+                _found;                                         \
+        })
+
+#if 0 /// UNNEEDED by elogind
 int path_strv_make_absolute_cwd(char **l);
 #endif // 0
 char** path_strv_resolve(char **l, const char *prefix);
@@ -117,8 +136,7 @@ bool path_is_safe(const char *p) _pure_;
 
 char *file_in_same_dir(const char *path, const char *filename);
 
-bool hidden_file_allow_backup(const char *filename);
-bool hidden_file(const char *filename) _pure_;
+bool hidden_or_backup_file(const char *filename) _pure_;
 
 #if 0 /// UNNEEDED by elogind
 bool is_device_path(const char *path);
index 62c801fe49ffa7d8f52c6ee2be2e16069f701f93..60a4e23226c57c8e4fdd18748f9efa2f699b557f 100644 (file)
@@ -161,17 +161,29 @@ static const char * const rlmap[] = {
         "3",         SPECIAL_MULTI_USER_TARGET,
         "4",         SPECIAL_MULTI_USER_TARGET,
         "5",         SPECIAL_GRAPHICAL_TARGET,
+        NULL
+};
+
+static const char * const rlmap_initrd[] = {
+        "emergency", SPECIAL_EMERGENCY_TARGET,
+        "rescue",    SPECIAL_RESCUE_TARGET,
+        NULL
 };
 
 const char* runlevel_to_target(const char *word) {
         size_t i;
+        const char * const *rlmap_ptr = in_initrd() ? rlmap_initrd
+                                                    : rlmap;
 
         if (!word)
                 return NULL;
 
-        for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
-                if (streq(word, rlmap[i]))
-                        return rlmap[i+1];
+        if (in_initrd() && (word = startswith(word, "rd.")) == NULL)
+                return NULL;
+
+        for (i = 0; rlmap_ptr[i] != NULL; i += 2)
+                if (streq(word, rlmap_ptr[i]))
+                        return rlmap_ptr[i+1];
 
         return NULL;
 }
index 550419d5ed608082bca14c7f7ae5e538a0f90f7b..cd9c0f7e5d5155abf9ea63fed1d6b7b292112ec4 100644 (file)
@@ -38,6 +38,7 @@
 #endif
 
 #include "alloc-util.h"
+//#include "architecture.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -100,6 +101,7 @@ 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) {
         _cleanup_fclose_ FILE *f = NULL;
+        bool space = false;
         char *r = NULL, *k;
         const char *p;
         int c;
@@ -107,6 +109,15 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
         assert(line);
         assert(pid >= 0);
 
+        /* Retrieves a process' command line. Replaces unprintable characters while doing so by whitespace (coalescing
+         * multiple sequential ones into one). If max_length is != 0 will return a string of the specified size at most
+         * (the trailing NUL byte does count towards the length here!), abbreviated with a "..." ellipsis. If
+         * comm_fallback is true and the process has no command line set (the case for kernel threads), or has a
+         * command line that resolves to the empty string will return the "comm" name of the process instead.
+         *
+         * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
+         * comm_fallback is false). */
+
         p = procfs_file_alloca(pid, "cmdline");
 
         f = fopen(p, "re");
@@ -116,24 +127,44 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                 return -errno;
         }
 
-        if (max_length == 0) {
+        if (max_length == 1) {
+
+                /* If there's only room for one byte, return the empty string */
+                r = new0(char, 1);
+                if (!r)
+                        return -ENOMEM;
+
+                *line = r;
+                return 0;
+
+        } else if (max_length == 0) {
                 size_t len = 0, allocated = 0;
 
                 while ((c = getc(f)) != EOF) {
 
-                        if (!GREEDY_REALLOC(r, allocated, len+2)) {
+                        if (!GREEDY_REALLOC(r, allocated, len+3)) {
                                 free(r);
                                 return -ENOMEM;
                         }
 
-                        r[len++] = isprint(c) ? c : ' ';
-                }
+                        if (isprint(c)) {
+                                if (space) {
+                                        r[len++] = ' ';
+                                        space = false;
+                                }
+
+                                r[len++] = c;
+                        } else if (len > 0)
+                                space = true;
+               }
 
                 if (len > 0)
-                        r[len-1] = 0;
+                        r[len] = 0;
+                else
+                        r = mfree(r);
 
         } else {
-                bool space = false;
+                bool dotdotdot = false;
                 size_t left;
 
                 r = new(char, max_length);
@@ -145,28 +176,46 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                 while ((c = getc(f)) != EOF) {
 
                         if (isprint(c)) {
+
                                 if (space) {
-                                        if (left <= 4)
+                                        if (left <= 2) {
+                                                dotdotdot = true;
                                                 break;
+                                        }
 
                                         *(k++) = ' ';
                                         left--;
                                         space = false;
                                 }
 
-                                if (left <= 4)
+                                if (left <= 1) {
+                                        dotdotdot = true;
                                         break;
+                                }
 
                                 *(k++) = (char) c;
                                 left--;
-                        }  else
+                        } else if (k > r)
                                 space = true;
                 }
 
-                if (left <= 4) {
-                        size_t n = MIN(left-1, 3U);
-                        memcpy(k, "...", n);
-                        k[n] = 0;
+                if (dotdotdot) {
+                        if (max_length <= 4) {
+                                k = r;
+                                left = max_length;
+                        } else {
+                                k = r + max_length - 4;
+                                left = 4;
+
+                                /* Eat up final spaces */
+                                while (k > r && isspace(k[-1])) {
+                                        k--;
+                                        left++;
+                                }
+                        }
+
+                        strncpy(k, "...", left-1);
+                        k[left-1] = 0;
                 } else
                         *k = 0;
         }
@@ -185,7 +234,37 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                 if (h < 0)
                         return h;
 
-                r = strjoin("[", t, "]", NULL);
+                if (max_length == 0)
+                        r = strjoin("[", t, "]", NULL);
+                else {
+                        size_t l;
+
+                        l = strlen(t);
+
+                        if (l + 3 <= max_length)
+                                r = strjoin("[", t, "]", NULL);
+                        else if (max_length <= 6) {
+
+                                r = new(char, max_length);
+                                if (!r)
+                                        return -ENOMEM;
+
+                                memcpy(r, "[...]", max_length-1);
+                                r[max_length-1] = 0;
+                        } else {
+                                char *e;
+
+                                t[max_length - 6] = 0;
+
+                                /* Chop off final spaces */
+                                e = strchr(t, 0);
+                                while (e > t && isspace(e[-1]))
+                                        e--;
+                                *e = 0;
+
+                                r = strjoin("[", t, "...]", NULL);
+                        }
+                }
                 if (!r)
                         return -ENOMEM;
         }
@@ -206,7 +285,7 @@ void rename_process(const char name[8]) {
          * "systemd"). If you pass a longer string it will be
          * truncated */
 
-        prctl(PR_SET_NAME, name);
+        (void) prctl(PR_SET_NAME, name);
 
         if (program_invocation_name)
                 strncpy(program_invocation_name, name, strlen(program_invocation_name));
@@ -320,9 +399,6 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
         assert(field);
         assert(uid);
 
-        if (pid == 0)
-                return getuid();
-
         p = procfs_file_alloca(pid, "status");
         f = fopen(p, "re");
         if (!f) {
@@ -412,7 +488,7 @@ int get_process_environ(pid_t pid, char **env) {
                 if (!outcome)
                         return -ENOMEM;
         } else
-        outcome[sz] = '\0';
+                outcome[sz] = '\0';
 
         *env = outcome;
         outcome = NULL;
@@ -482,7 +558,7 @@ int wait_for_terminate(pid_t pid, siginfo_t *status) {
                         if (errno == EINTR)
                                 continue;
 
-                        return -errno;
+                        return negative_errno();
                 }
 
                 return 0;
@@ -533,24 +609,32 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_cod
         return -EPROTO;
 }
 
-void sigkill_wait(pid_t *pid) {
+#if 0 /// UNNEEDED by elogind
+void sigkill_wait(pid_t pid) {
+        assert(pid > 1);
+
+        if (kill(pid, SIGKILL) > 0)
+                (void) wait_for_terminate(pid, NULL);
+}
+
+void sigkill_waitp(pid_t *pid) {
         if (!pid)
                 return;
         if (*pid <= 1)
                 return;
 
-        if (kill(*pid, SIGKILL) > 0)
-                (void) wait_for_terminate(*pid, NULL);
+        sigkill_wait(*pid);
 }
 
-#if 0 /// UNNEEDED by elogind
 int kill_and_sigcont(pid_t pid, int sig) {
         int r;
 
         r = kill(pid, sig) < 0 ? -errno : 0;
 
-        if (r >= 0)
-                kill(pid, SIGCONT);
+        /* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't
+         * affected by a process being suspended anyway. */
+        if (r >= 0 && !IN_SET(SIGCONT, SIGKILL))
+                (void) kill(pid, SIGCONT);
 
         return r;
 }
@@ -671,6 +755,8 @@ bool is_main_thread(void) {
 #if 0 /// UNNEEDED by elogind
 noreturn void freeze(void) {
 
+        log_close();
+
         /* Make sure nobody waits for us on a socket anymore */
         close_all_fds(NULL, 0);
 
@@ -685,82 +771,50 @@ bool oom_score_adjust_is_valid(int oa) {
 }
 
 unsigned long personality_from_string(const char *p) {
+        int architecture;
 
-        /* Parse a personality specifier. We introduce our own
-         * identifiers that indicate specific ABIs, rather than just
-         * hints regarding the register size, since we want to keep
-         * things open for multiple locally supported ABIs for the
-         * same register size. We try to reuse the ABI identifiers
-         * used by libseccomp. */
-
-#if defined(__x86_64__)
-
-        if (streq(p, "x86"))
-                return PER_LINUX32;
+        if (!p)
+                return PERSONALITY_INVALID;
 
-        if (streq(p, "x86-64"))
-                return PER_LINUX;
+        /* Parse a personality specifier. We use our own identifiers that indicate specific ABIs, rather than just
+         * hints regarding the register size, since we want to keep things open for multiple locally supported ABIs for
+         * the same register size. */
 
-#elif defined(__i386__)
+        architecture = architecture_from_string(p);
+        if (architecture < 0)
+                return PERSONALITY_INVALID;
 
-        if (streq(p, "x86"))
+        if (architecture == native_architecture())
                 return PER_LINUX;
-
-#elif defined(__s390x__)
-
-        if (streq(p, "s390"))
+#ifdef SECONDARY_ARCHITECTURE
+        if (architecture == SECONDARY_ARCHITECTURE)
                 return PER_LINUX32;
-
-        if (streq(p, "s390x"))
-                return PER_LINUX;
-
-#elif defined(__s390__)
-
-        if (streq(p, "s390"))
-                return PER_LINUX;
 #endif
 
         return PERSONALITY_INVALID;
 }
 
 const char* personality_to_string(unsigned long p) {
-
-#if defined(__x86_64__)
-
-        if (p == PER_LINUX32)
-                return "x86";
+        int architecture = _ARCHITECTURE_INVALID;
 
         if (p == PER_LINUX)
-                return "x86-64";
-
-#elif defined(__i386__)
-
-        if (p == PER_LINUX)
-                return "x86";
-
-#elif defined(__s390x__)
-
-        if (p == PER_LINUX)
-                return "s390x";
-
-        if (p == PER_LINUX32)
-                return "s390";
-
-#elif defined(__s390__)
-
-        if (p == PER_LINUX)
-                return "s390";
-
+                architecture = native_architecture();
+#ifdef SECONDARY_ARCHITECTURE
+        else if (p == PER_LINUX32)
+                architecture = SECONDARY_ARCHITECTURE;
 #endif
 
-        return NULL;
+        if (architecture < 0)
+                return NULL;
+
+        return architecture_to_string(architecture);
 }
 
 void valgrind_summary_hack(void) {
 #ifdef HAVE_VALGRIND_VALGRIND_H
         if (getpid() == 1 && RUNNING_ON_VALGRIND) {
                 pid_t pid;
-                pid = raw_clone(SIGCHLD, NULL);
+                pid = raw_clone(SIGCHLD);
                 if (pid < 0)
                         log_emergency_errno(errno, "Failed to fork off valgrind helper: %m");
                 else if (pid == 0)
@@ -773,6 +827,18 @@ void valgrind_summary_hack(void) {
 #endif
 }
 
+int pid_compare_func(const void *a, const void *b) {
+        const pid_t *p = a, *q = b;
+
+        /* Suitable for usage in qsort() */
+
+        if (*p < *q)
+                return -1;
+        if (*p > *q)
+                return 1;
+        return 0;
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
index d9c62aa9c7922c95ab2cd51bfa3efd73046ca098..6cf3a40b1f6dd83cd3dd626fb2fd2ff0d68b9b41 100644 (file)
@@ -47,7 +47,6 @@ int get_process_state(pid_t pid);
 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);
-
 #if 0 /// UNNEEDED by elogind
 int get_process_uid(pid_t pid, uid_t *uid);
 int get_process_gid(pid_t pid, gid_t *gid);
@@ -61,15 +60,14 @@ int get_process_ppid(pid_t pid, pid_t *ppid);
 int wait_for_terminate(pid_t pid, siginfo_t *status);
 int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
 
-void sigkill_wait(pid_t *pid);
-#define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait)
-
 #if 0 /// UNNEEDED by elogind
+void sigkill_wait(pid_t pid);
+void sigkill_waitp(pid_t *pid);
+
 int kill_and_sigcont(pid_t pid, int sig);
 
 void rename_process(const char name[8]);
 #endif // 0
-
 int is_kernel_thread(pid_t pid);
 
 int getenv_for_pid(pid_t pid, const char *field, char **_value);
@@ -113,3 +111,5 @@ int sched_policy_from_string(const char *s);
 #define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
 
 void valgrind_summary_hack(void);
+
+int pid_compare_func(const void *a, const void *b);
index 2f468db770d6d24fd8fa838dc8aa5a195f34d5b1..ad7b3eedf2c1d5ffb7ca92662bff43e070878872 100644 (file)
@@ -46,7 +46,7 @@ int dev_urandom(void *p, size_t n) {
          * never block, and will always return some data from the
          * kernel, regardless if the random pool is fully initialized
          * or not. It thus makes no guarantee for the quality of the
-         * returned entropy, but is good enough for or usual usecases
+         * returned entropy, but is good enough for our usual usecases
          * of seeding the hash functions for hashtable */
 
         /* Use the getrandom() syscall unless we know we don't have
index 6912b23f5fc89430389ca6a96c1b5c2c1a479ef5..474bfbf43586771417ea9fa3504ae0d5ca1e9260 100644 (file)
@@ -128,7 +128,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
                                 continue;
                         }
 
-#if 0
+#if 0 /// elogind does not support BTRFS this directly
                         if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
 
                                 /* This could be a subvolume, try to remove it */
@@ -190,7 +190,7 @@ int rm_rf(const char *path, RemoveFlags flags) {
                 return -EPERM;
         }
 
-#if 0
+#if 0 /// elogind does not support BTRFS this directly
         if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) {
                 /* Try to remove as subvolume first */
                 r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
index 6d032689190266f9f6429d42f0deb9558c8fc631..f693a5bb7c52bbadbf8424f9edde4d8f65952b02 100644 (file)
@@ -30,3 +30,12 @@ typedef enum RemoveFlags {
 
 int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev);
 int rm_rf(const char *path, RemoveFlags flags);
+
+/* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */
+static inline void rm_rf_physical_and_free(char *p) {
+        if (!p)
+                return;
+        (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
+        free(p);
+}
+DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rm_rf_physical_and_free);
index 700b2e82960d3f5898f69e4544573c24fd8e18e1..021041cbdccd195558bebe2111b9b1b6cb5850a6 100644 (file)
 #include "util.h"
 
 #ifdef HAVE_SELINUX
-DEFINE_TRIVIAL_CLEANUP_FUNC(security_context_t, freecon);
+DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon);
 DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
 
-#define _cleanup_security_context_free_ _cleanup_(freeconp)
+#define _cleanup_freecon_ _cleanup_(freeconp)
 #define _cleanup_context_free_ _cleanup_(context_freep)
 
 static int cached_use = -1;
@@ -82,31 +82,23 @@ void mac_selinux_retest(void) {
 }
 #endif // 0
 
-int mac_selinux_init(const char *prefix) {
+int mac_selinux_init(void) {
         int r = 0;
 
 #ifdef HAVE_SELINUX
         usec_t before_timestamp, after_timestamp;
         struct mallinfo before_mallinfo, after_mallinfo;
 
-        if (!mac_selinux_use())
+        if (label_hnd)
                 return 0;
 
-        if (label_hnd)
+        if (!mac_selinux_use())
                 return 0;
 
         before_mallinfo = mallinfo();
         before_timestamp = now(CLOCK_MONOTONIC);
 
-        if (prefix) {
-                struct selinux_opt options[] = {
-                        { .type = SELABEL_OPT_SUBSET, .value = prefix },
-                };
-
-                label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options));
-        } else
-                label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
-
+        label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
         if (!label_hnd) {
                 log_enforcing("Failed to initialize SELinux context: %m");
                 r = security_getenforce() == 1 ? -errno : 0;
@@ -155,7 +147,7 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
 
         r = lstat(path, &st);
         if (r >= 0) {
-                _cleanup_security_context_free_ security_context_t fcon = NULL;
+                _cleanup_freecon_ char* fcon = NULL;
 
                 r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
 
@@ -164,7 +156,7 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
                         return 0;
 
                 if (r >= 0) {
-                        r = lsetfilecon(path, fcon);
+                        r = lsetfilecon_raw(path, fcon);
 
                         /* If the FS doesn't support labels, then exit without warning */
                         if (r < 0 && errno == EOPNOTSUPP)
@@ -199,7 +191,7 @@ int mac_selinux_apply(const char *path, const char *label) {
         assert(path);
         assert(label);
 
-        if (setfilecon(path, (security_context_t) label) < 0) {
+        if (setfilecon(path, label) < 0) {
                 log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path);
                 if (security_getenforce() > 0)
                         return -errno;
@@ -212,7 +204,7 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
         int r = -EOPNOTSUPP;
 
 #ifdef HAVE_SELINUX
-        _cleanup_security_context_free_ security_context_t mycon = NULL, fcon = NULL;
+        _cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
         security_class_t sclass;
 
         assert(exe);
@@ -230,7 +222,7 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
                 return -errno;
 
         sclass = string_to_security_class("process");
-        r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+        r = security_compute_create_raw(mycon, fcon, sclass, label);
         if (r < 0)
                 return -errno;
 #endif
@@ -259,7 +251,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
         int r = -EOPNOTSUPP;
 
 #ifdef HAVE_SELINUX
-        _cleanup_security_context_free_ security_context_t mycon = NULL, peercon = NULL, fcon = NULL;
+        _cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL;
         _cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
         security_class_t sclass;
         const char *range = NULL;
@@ -275,7 +267,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
         if (r < 0)
                 return -errno;
 
-        r = getpeercon(socket_fd, &peercon);
+        r = getpeercon_raw(socket_fd, &peercon);
         if (r < 0)
                 return -errno;
 
@@ -309,7 +301,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
                 return -ENOMEM;
 
         sclass = string_to_security_class("process");
-        r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+        r = security_compute_create_raw(mycon, fcon, sclass, label);
         if (r < 0)
                 return -errno;
 #endif
@@ -327,7 +319,7 @@ char* mac_selinux_free(char *label) {
                 return NULL;
 
 
-        freecon((security_context_t) label);
+        freecon(label);
 #endif
 
         return NULL;
@@ -337,7 +329,7 @@ char* mac_selinux_free(char *label) {
 int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
 
 #ifdef HAVE_SELINUX
-        _cleanup_security_context_free_ security_context_t filecon = NULL;
+        _cleanup_freecon_ char *filecon = NULL;
         int r;
 
         assert(path);
@@ -358,16 +350,16 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
         }
 
         if (r < 0) {
-        /* No context specified by the policy? Proceed without setting it. */
+                /* No context specified by the policy? Proceed without setting it. */
                 if (errno == ENOENT)
-                return 0;
+                        return 0;
 
                 log_enforcing("Failed to determine SELinux security context for %s: %m", path);
         } else {
-                if (setfscreatecon(filecon) >= 0)
+                if (setfscreatecon_raw(filecon) >= 0)
                         return 0; /* Success! */
 
-                        log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
+                log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
         }
 
         if (security_getenforce() > 0)
@@ -385,7 +377,7 @@ void mac_selinux_create_file_clear(void) {
         if (!mac_selinux_use())
                 return;
 
-        setfscreatecon(NULL);
+        setfscreatecon_raw(NULL);
 #endif
 }
 
@@ -398,7 +390,7 @@ int mac_selinux_create_socket_prepare(const char *label) {
 
         assert(label);
 
-        if (setsockcreatecon((security_context_t) label) < 0) {
+        if (setsockcreatecon(label) < 0) {
                 log_enforcing("Failed to set SELinux security context %s for sockets: %m", label);
 
                 if (security_getenforce() == 1)
@@ -417,7 +409,7 @@ void mac_selinux_create_socket_clear(void) {
         if (!mac_selinux_use())
                 return;
 
-        setsockcreatecon(NULL);
+        setsockcreatecon_raw(NULL);
 #endif
 }
 
@@ -426,7 +418,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
         /* Binds a socket and label its file system object according to the SELinux policy */
 
 #ifdef HAVE_SELINUX
-        _cleanup_security_context_free_ security_context_t fcon = NULL;
+        _cleanup_freecon_ char *fcon = NULL;
         const struct sockaddr_un *un;
         bool context_changed = false;
         char *path;
@@ -476,7 +468,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
                         return -errno;
 
         } else {
-                if (setfscreatecon(fcon) < 0) {
+                if (setfscreatecon_raw(fcon) < 0) {
                         log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
                         if (security_getenforce() > 0)
                                 return -errno;
@@ -487,7 +479,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
         r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
 
         if (context_changed)
-        setfscreatecon(NULL);
+                setfscreatecon_raw(NULL);
 
         return r;
 
index e2d21a48636e769c61386d65310c68cce443ee77..0528b77592371dd5d5cd2d43e70aadfc93dc40b3 100644 (file)
@@ -31,7 +31,7 @@ bool mac_selinux_have(void);
 void mac_selinux_retest(void);
 #endif // 0
 
-int mac_selinux_init(const char *prefix);
+int mac_selinux_init(void);
 #if 0 /// UNNEEDED by elogind
 void mac_selinux_finish(void);
 #endif // 0
index f8e86478cb83b905b8e26f4bd744114c95c325b7..5a5c8edb463f1b587010b61e1899bad941e10f7d 100644 (file)
@@ -125,11 +125,15 @@ int set_consume(Set *s, void *value);
 int set_put_strdup(Set *s, const char *p);
 #if 0 /// UNNEEDED by elogind
 int set_put_strdupv(Set *s, char **l);
+int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
 #endif // 0
 
 #define SET_FOREACH(e, s, i) \
         for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); )
 
+#define SET_FOREACH_MOVE(e, d, s)                                       \
+        for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); )
+
 DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
 DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
 
index 2e452f86644937fba97d4e48a439725ae54feb61..0be2ec0c708ee983a8abdefcf8430407d3f3d078 100644 (file)
@@ -259,7 +259,7 @@ int signal_from_string(const char *s) {
         }
         if (safe_atou(s, &u) >= 0) {
                 signo = (int) u + offset;
-                if (signo > 0 && signo < _NSIG)
+                if (SIGNAL_VALID(signo))
                         return signo;
         }
         return -EINVAL;
index 7013c51a3d9aaa4385ec3321bd405b6a107f5e25..ee37e2726e14e686cad101ea0b0946f6eb9567e1 100644 (file)
@@ -48,9 +48,13 @@ static inline void block_signals_reset(sigset_t *ss) {
         assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0);
 }
 
-#define BLOCK_SIGNALS(...)                                              \
-        _cleanup_(block_signals_reset) sigset_t _saved_sigset = ({      \
-                sigset_t t;                                             \
+#define BLOCK_SIGNALS(...)                                                        \
+        _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({       \
+                sigset_t t;                                                       \
                 assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \
-                t;                                                      \
+                t;                                                                \
         })
+
+static inline bool SIGNAL_VALID(int signo) {
+        return signo > 0 && signo < _NSIG;
+}
index 8edaae51197e22eeacdcb2f3f3315829f8718fd5..8c1cdc3db6afd6bc8a1a13cfa0e05e5f24a5bc6e 100644 (file)
@@ -17,6 +17,8 @@
     coding style)
 */
 
+#include <stdio.h>
+
 #include "macro.h"
 #include "siphash24.h"
 #include "unaligned.h"
@@ -56,7 +58,7 @@ void siphash24_init(struct siphash *state, const uint8_t k[16]) {
         k1 = unaligned_read_le64(k + 8);
 
         *state = (struct siphash) {
-  /* "somepseudorandomlygeneratedbytes" */
+                /* "somepseudorandomlygeneratedbytes" */
                 .v0 = 0x736f6d6570736575ULL ^ k0,
                 .v1 = 0x646f72616e646f6dULL ^ k1,
                 .v2 = 0x6c7967656e657261ULL ^ k0,
@@ -77,16 +79,16 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
         assert(state);
 
         /* Update total length */
-  state->inlen += inlen;
+        state->inlen += inlen;
 
         /* If padding exists, fill it out */
-  if (left > 0) {
-    for ( ; in < end && left < 8; in ++, left ++ )
-                        state->padding |= ( ( uint64_t )*in ) << (left * 8);
+        if (left > 0) {
+                for ( ; in < end && left < 8; in ++, left ++)
+                        state->padding |= ((uint64_t) *in) << (left * 8);
 
-    if (in == end && left < 8)
+                if (in == end && left < 8)
                         /* We did not have enough input to fill out the padding completely */
-      return;
+                        return;
 
 #ifdef DEBUG
                 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -96,17 +98,17 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
                 printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
 #endif
 
-    state->v3 ^= state->padding;
+                state->v3 ^= state->padding;
                 sipround(state);
                 sipround(state);
-    state->v0 ^= state->padding;
+                state->v0 ^= state->padding;
 
-    state->padding = 0;
-  }
+                state->padding = 0;
+        }
 
-        end -= ( state->inlen % sizeof (uint64_t) );
+        end -= (state->inlen % sizeof(uint64_t));
 
-        for ( ; in < end; in += 8 ) {
+        for ( ; in < end; in += 8) {
                 m = unaligned_read_le64(in);
 #ifdef DEBUG
                 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -115,13 +117,13 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
                 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
                 printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
 #endif
-    state->v3 ^= m;
+                state->v3 ^= m;
                 sipround(state);
                 sipround(state);
-    state->v0 ^= m;
-  }
+                state->v0 ^= m;
+        }
 
-  left = state->inlen & 7;
+        left = state->inlen & 7;
         switch (left) {
                 case 7:
                         state->padding |= ((uint64_t) in[6]) << 48;
@@ -139,7 +141,7 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
                         state->padding |= ((uint64_t) in[0]);
                 case 0:
                         break;
-  }
+        }
 }
 
 uint64_t siphash24_finalize(struct siphash *state) {
@@ -147,20 +149,20 @@ uint64_t siphash24_finalize(struct siphash *state) {
 
         assert(state);
 
-        b = state->padding | (( ( uint64_t )state->inlen ) << 56);
+        b = state->padding | (((uint64_t) state->inlen) << 56);
 
 #ifdef DEBUG
-        printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t)state->v0);
-        printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t)state->v1);
-        printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t)state->v2);
-        printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t)state->v3);
+        printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
+        printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
+        printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
+        printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
         printf("(%3zu) padding   %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
 #endif
 
-  state->v3 ^= b;
+        state->v3 ^= b;
         sipround(state);
         sipround(state);
-  state->v0 ^= b;
+        state->v0 ^= b;
 
 #ifdef DEBUG
         printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -168,7 +170,7 @@ uint64_t siphash24_finalize(struct siphash *state) {
         printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
         printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
 #endif
-  state->v2 ^= 0xff;
+        state->v2 ^= 0xff;
 
         sipround(state);
         sipround(state);
@@ -179,7 +181,7 @@ uint64_t siphash24_finalize(struct siphash *state) {
 }
 
 uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
-  struct siphash state;
+        struct siphash state;
 
         assert(in);
         assert(k);
index 73e19310e065eb2f112d207b13f23221085facf9..f47a8f04e0399c16233ebad5b9b8481681363e9c 100644 (file)
@@ -42,6 +42,7 @@
 #include "socket-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "strv.h"
 #include "user-util.h"
 #include "util.h"
 
@@ -83,7 +84,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         return -EINVAL;
 
                 a->sockaddr.in6.sin6_family = AF_INET6;
-                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                 a->size = sizeof(struct sockaddr_in6);
 
         } else if (*s == '/') {
@@ -131,7 +132,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         if (r > 0) {
                                 /* Gotcha, it's a traditional IPv4 address */
                                 a->sockaddr.in.sin_family = AF_INET;
-                                a->sockaddr.in.sin_port = htons((uint16_t) u);
+                                a->sockaddr.in.sin_port = htobe16((uint16_t)u);
                                 a->size = sizeof(struct sockaddr_in);
                         } else {
                                 unsigned idx;
@@ -145,7 +146,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                                         return -EINVAL;
 
                                 a->sockaddr.in6.sin6_family = AF_INET6;
-                                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                                 a->sockaddr.in6.sin6_scope_id = idx;
                                 a->sockaddr.in6.sin6_addr = in6addr_any;
                                 a->size = sizeof(struct sockaddr_in6);
@@ -162,12 +163,12 @@ int socket_address_parse(SocketAddress *a, const char *s) {
 
                         if (socket_ipv6_is_supported()) {
                                 a->sockaddr.in6.sin6_family = AF_INET6;
-                                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                                 a->sockaddr.in6.sin6_addr = in6addr_any;
                                 a->size = sizeof(struct sockaddr_in6);
                         } else {
                                 a->sockaddr.in.sin_family = AF_INET;
-                                a->sockaddr.in.sin_port = htons((uint16_t) u);
+                                a->sockaddr.in.sin_port = htobe16((uint16_t)u);
                                 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
                                 a->size = sizeof(struct sockaddr_in);
                         }
@@ -488,9 +489,7 @@ int sockaddr_port(const struct sockaddr *_sa) {
         if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
                 return -EAFNOSUPPORT;
 
-        return ntohs(sa->sa.sa_family == AF_INET6 ?
-                       sa->in6.sin6_port :
-                       sa->in.sin_port);
+        return be16toh(sa->sa.sa_family == AF_INET6 ? sa->in6.sin6_port : sa->in.sin_port);
 }
 
 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
@@ -506,13 +505,13 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
         case AF_INET: {
                 uint32_t a;
 
-                a = ntohl(sa->in.sin_addr.s_addr);
+                a = be32toh(sa->in.sin_addr.s_addr);
 
                 if (include_port)
                         r = asprintf(&p,
                                      "%u.%u.%u.%u:%u",
                                      a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
-                                     ntohs(sa->in.sin_port));
+                                     be16toh(sa->in.sin_port));
                 else
                         r = asprintf(&p,
                                      "%u.%u.%u.%u",
@@ -534,7 +533,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
                                 r = asprintf(&p,
                                              "%u.%u.%u.%u:%u",
                                              a[0], a[1], a[2], a[3],
-                                             ntohs(sa->in6.sin6_port));
+                                             be16toh(sa->in6.sin6_port));
                         else
                                 r = asprintf(&p,
                                              "%u.%u.%u.%u",
@@ -550,7 +549,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
                                 r = asprintf(&p,
                                              "[%s]:%u",
                                              a,
-                                             ntohs(sa->in6.sin6_port));
+                                             be16toh(sa->in6.sin6_port));
                                 if (r < 0)
                                         return -ENOMEM;
                         } else {
@@ -800,6 +799,42 @@ static const char* const ip_tos_table[] = {
 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
 #endif // 0
 
+bool ifname_valid(const char *p) {
+        bool numeric = true;
+
+        /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
+         * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
+         * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
+
+        if (isempty(p))
+                return false;
+
+        if (strlen(p) >= IFNAMSIZ)
+                return false;
+
+        if (STR_IN_SET(p, ".", ".."))
+                return false;
+
+        while (*p) {
+                if ((unsigned char) *p >= 127U)
+                        return false;
+
+                if ((unsigned char) *p <= 32U)
+                        return false;
+
+                if (*p == ':' || *p == '/')
+                        return false;
+
+                numeric = numeric && (*p >= '0' && *p <= '9');
+                p++;
+        }
+
+        if (numeric)
+                return false;
+
+        return true;
+}
+
 int getpeercred(int fd, struct ucred *ucred) {
         socklen_t n = sizeof(struct ucred);
         struct ucred u;
@@ -943,4 +978,77 @@ int receive_one_fd(int transport_fd, int flags) {
 
         return *(int*) CMSG_DATA(found);
 }
+
+ssize_t next_datagram_size_fd(int fd) {
+        ssize_t l;
+        int k;
+
+        /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
+         * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
+         * do. This difference is actually of major importance as we need to be sure that the size returned here
+         * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
+         * the wrong size. */
+
+        l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
+        if (l < 0) {
+                if (errno == EOPNOTSUPP || errno == EFAULT)
+                        goto fallback;
+
+                return -errno;
+        }
+        if (l == 0)
+                goto fallback;
+
+        return l;
+
+fallback:
+        k = 0;
+
+        /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
+         * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
+
+        if (ioctl(fd, FIONREAD, &k) < 0)
+                return -errno;
+
+        return (ssize_t) k;
+}
+
+int flush_accept(int fd) {
+
+        struct pollfd pollfd = {
+                .fd = fd,
+                .events = POLLIN,
+        };
+        int r;
+
+
+        /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
+
+        for (;;) {
+                int cfd;
+
+                r = poll(&pollfd, 1, 0);
+                if (r < 0) {
+                        if (errno == EINTR)
+                                continue;
+
+                        return -errno;
+
+                } else if (r == 0)
+                        return 0;
+
+                cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+                if (cfd < 0) {
+                        if (errno == EINTR)
+                                continue;
+
+                        if (errno == EAGAIN)
+                                return 0;
+
+                        return -errno;
+                }
+
+                close(cfd);
+        }
+}
 #endif // 0
index 449273d9a2c3d1ccd55b35797544ec647f55a245..b5d1dc3ed45b0bbf7296e6b9a3625b0a9067eb74 100644 (file)
@@ -129,6 +129,8 @@ int ip_tos_to_string_alloc(int i, char **s);
 int ip_tos_from_string(const char *s);
 #endif // 0
 
+bool ifname_valid(const char *p);
+
 int getpeercred(int fd, struct ucred *ucred);
 int getpeersec(int fd, char **ret);
 
@@ -139,7 +141,22 @@ int send_one_fd_sa(int transport_fd,
 #define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags)
 #if 0 /// UNNEEDED by elogind
 int receive_one_fd(int transport_fd, int flags);
+
+ssize_t next_datagram_size_fd(int fd);
+
+int flush_accept(int fd);
 #endif // 0
 
 #define CMSG_FOREACH(cmsg, mh)                                          \
         for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
+
+/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
+#define SOCKADDR_UN_LEN(sa)                                             \
+        ({                                                              \
+                const struct sockaddr_un *_sa = &(sa);                  \
+                assert(_sa->sun_family == AF_UNIX);                     \
+                offsetof(struct sockaddr_un, sun_path) +                \
+                        (_sa->sun_path[0] == 0 ?                        \
+                         1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
+                         strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \
+        })
index 60cf86a532813bd1ad3c0ae655bb0f1b3b730b40..3e0ea04f6448344129fb25c86b88dae714fea2d5 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#if defined(__GLIBC__) && defined(HAVE_PRINTF_H)
+#if 0 /// elogind is musl-libc compatible and does not directly include printf.h
 #include <printf.h>
 #else
 #include "parse-printf-format.h"
-#endif
+#endif // 0
 #include <stdarg.h>
 #include <stdio.h>
 #include <sys/types.h>
@@ -77,4 +77,4 @@ do {                                                                    \
                         assert_not_reached("Unknown format string argument."); \
                 }                                                       \
         }                                                               \
-} while(false)
+} while (false)
index b180488fe86d950a78c6aef29892bb921a88b0ad..369610efc8ca0c77ad4d7d591172f8c180662c01 100644 (file)
@@ -48,6 +48,8 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
 #define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
         scope type name##_from_string(const char *s) {                  \
                 int b;                                                  \
+                if (!s)                                                 \
+                        return -1;                                      \
                 b = parse_boolean(s);                                   \
                 if (b == 0)                                             \
                         return (type) 0;                                \
@@ -56,26 +58,8 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
                 return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
         }
 
-#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope)                    \
-        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
-        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)        \
-        struct __useless_struct_to_allow_trailing_semicolon__
-
-#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope)   \
-        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
-        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
-        struct __useless_struct_to_allow_trailing_semicolon__
-
-#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
-
-#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
-
-/* For string conversions where numbers are also acceptable */
-#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max)         \
-        int name##_to_string_alloc(type i, char **str) {                \
+#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,scope) \
+        scope int name##_to_string_alloc(type i, char **str) {          \
                 char *s;                                                \
                 if (i < 0 || i > max)                                   \
                         return -ERANGE;                                 \
@@ -89,7 +73,9 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
                 }                                                       \
                 *str = s;                                               \
                 return 0;                                               \
-        }                                                               \
+        }
+
+#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \
         type name##_from_string(const char *s) {                        \
                 type i;                                                 \
                 unsigned u = 0;                                         \
@@ -102,4 +88,32 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
                         return (type) u;                                \
                 return (type) -1;                                       \
         }                                                               \
+
+
+#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope)                    \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)        \
+        struct __useless_struct_to_allow_trailing_semicolon__
+
+#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope)   \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
+        struct __useless_struct_to_allow_trailing_semicolon__
+
+#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
+
+#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
+
+/* For string conversions where numbers are also acceptable */
+#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max)         \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,)  \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \
         struct __useless_struct_to_allow_trailing_semicolon__
+
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
index 0bde55f9d5749a29e2e7b4e133cfb6d2ecb7543a..293a15f9c041cf59f5354829cfdc86b0b0622a20 100644 (file)
@@ -477,7 +477,7 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
         }
 
         if (k > x) /* last character was wide and went over quota */
-                x ++;
+                x++;
 
         for (j = s + old_length; k < new_length && j > i; ) {
                 char32_t c;
index ad0c813761ed9dc81dd9aa254b54421719cc0b20..1209e1e2e14c11853b526891d31b34584c36db68 100644 (file)
@@ -37,6 +37,7 @@
 #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 #define LETTERS           LOWERCASE_LETTERS UPPERCASE_LETTERS
 #define ALPHANUMERICAL    LETTERS DIGITS
+#define HEXDIGITS         DIGITS "abcdefABCDEF"
 
 #define streq(a,b) (strcmp((a),(b)) == 0)
 #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
@@ -65,6 +66,10 @@ static inline bool isempty(const char *p) {
         return !p || !p[0];
 }
 
+static inline const char *empty_to_null(const char *p) {
+        return isempty(p) ? NULL : p;
+}
+
 static inline char *startswith(const char *s, const char *prefix) {
         size_t l;
 
index 5c8261d9210d240e767c9c0af831c1dec106a2d9..baaa72e674dc98b3ca3126efc1e385019ef361d0 100644 (file)
@@ -139,16 +139,16 @@ char **strv_new_ap(const char *x, va_list ap) {
         va_list aq;
 
         /* As a special trick we ignore all listed strings that equal
-         * (const char*) -1. This is supposed to be used with the
+         * STRV_IGNORE. This is supposed to be used with the
          * STRV_IFNOTNULL() macro to include possibly NULL strings in
          * the string list. */
 
         if (x) {
-                n = x == (const char*) -1 ? 0 : 1;
+                n = x == STRV_IGNORE ? 0 : 1;
 
                 va_copy(aq, ap);
                 while ((s = va_arg(aq, const char*))) {
-                        if (s == (const char*) -1)
+                        if (s == STRV_IGNORE)
                                 continue;
 
                         n++;
@@ -162,7 +162,7 @@ char **strv_new_ap(const char *x, va_list ap) {
                 return NULL;
 
         if (x) {
-                if (x != (const char*) -1) {
+                if (x != STRV_IGNORE) {
                         a[i] = strdup(x);
                         if (!a[i])
                                 goto fail;
@@ -171,7 +171,7 @@ char **strv_new_ap(const char *x, va_list ap) {
 
                 while ((s = va_arg(ap, const char*))) {
 
-                        if (s == (const char*) -1)
+                        if (s == STRV_IGNORE)
                                 continue;
 
                         a[i] = strdup(s);
@@ -319,7 +319,7 @@ char **strv_split_newlines(const char *s) {
                 return l;
 
         if (isempty(l[n - 1]))
-                l[n-1] = mfree(l[n-1]);
+                l[n - 1] = mfree(l[n - 1]);
 
         return l;
 }
@@ -375,7 +375,7 @@ char *strv_join(char **l, const char *separator) {
 
         n = 0;
         STRV_FOREACH(s, l) {
-                if (n != 0)
+                if (s != l)
                         n += k;
                 n += strlen(*s);
         }
@@ -386,7 +386,7 @@ char *strv_join(char **l, const char *separator) {
 
         e = r;
         STRV_FOREACH(s, l) {
-                if (e != r)
+                if (s != l)
                         e = stpcpy(e, separator);
 
                 e = stpcpy(e, *s);
@@ -566,6 +566,42 @@ int strv_extend(char ***l, const char *value) {
         return strv_consume(l, v);
 }
 
+int strv_extend_front(char ***l, const char *value) {
+        size_t n, m;
+        char *v, **c;
+
+        assert(l);
+
+        /* Like strv_extend(), but prepends rather than appends the new entry */
+
+        if (!value)
+                return 0;
+
+        n = strv_length(*l);
+
+        /* Increase and overflow check. */
+        m = n + 2;
+        if (m < n)
+                return -ENOMEM;
+
+        v = strdup(value);
+        if (!v)
+                return -ENOMEM;
+
+        c = realloc_multiply(*l, sizeof(char*), m);
+        if (!c) {
+                free(v);
+                return -ENOMEM;
+        }
+
+        memmove(c+1, c, n * sizeof(char*));
+        c[0] = v;
+        c[n+1] = NULL;
+
+        *l = c;
+        return 0;
+}
+
 char **strv_uniq(char **l) {
         char **i;
 
@@ -612,6 +648,17 @@ char **strv_remove(char **l, const char *s) {
 }
 
 char **strv_parse_nulstr(const char *s, size_t l) {
+        /* l is the length of the input data, which will be split at NULs into
+         * elements of the resulting strv. Hence, the number of items in the resulting strv
+         * will be equal to one plus the number of NUL bytes in the l bytes starting at s,
+         * unless s[l-1] is NUL, in which case the final empty string is not stored in
+         * the resulting strv, and length is equal to the number of NUL bytes.
+         *
+         * Note that contrary to a normal nulstr which cannot contain empty strings, because
+         * the input data is terminated by any two consequent NUL bytes, this parser accepts
+         * empty strings in s.
+         */
+
         const char *p;
         unsigned c = 0, i = 0;
         char **v;
@@ -675,6 +722,13 @@ char **strv_split_nulstr(const char *s) {
 
 #if 0 /// UNNEEDED by elogind
 int strv_make_nulstr(char **l, char **p, size_t *q) {
+        /* A valid nulstr with two NULs at the end will be created, but
+         * q will be the length without the two trailing NULs. Thus the output
+         * string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
+         * and can also be parsed by strv_parse_nulstr as long as the length
+         * is provided separately.
+         */
+
         size_t n_allocated = 0, n = 0;
         _cleanup_free_ char *m = NULL;
         char **i;
@@ -687,7 +741,7 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
 
                 z = strlen(*i);
 
-                if (!GREEDY_REALLOC(m, n_allocated, n + z + 1))
+                if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
                         return -ENOMEM;
 
                 memcpy(m + n, *i, z + 1);
@@ -698,11 +752,14 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
                 m = new0(char, 1);
                 if (!m)
                         return -ENOMEM;
-                n = 0;
-        }
+                n = 1;
+        } else
+                /* make sure there is a second extra NUL at the end of resulting nulstr */
+                m[n] = '\0';
 
+        assert(n > 0);
         *p = m;
-        *q = n;
+        *q = n - 1;
 
         m = NULL;
 
@@ -780,13 +837,8 @@ char **strv_reverse(char **l) {
         if (n <= 1)
                 return l;
 
-        for (i = 0; i < n / 2; i++) {
-                char *t;
-
-                t = l[i];
-                l[i] = l[n-1-i];
-                l[n-1-i] = t;
-        }
+        for (i = 0; i < n / 2; i++)
+                SWAP_TWO(l[i], l[n-1-i]);
 
         return l;
 }
@@ -815,7 +867,7 @@ bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
         char* const* p;
 
         STRV_FOREACH(p, patterns)
-                if (fnmatch(*p, s, 0) == 0)
+                if (fnmatch(*p, s, flags) == 0)
                         return true;
 
         return false;
@@ -857,7 +909,7 @@ int strv_extend_n(char ***l, const char *value, size_t n) {
         if (n == 0)
                 return 0;
 
-        /* Adds the value value n times to l */
+        /* Adds the value n times to l */
 
         k = strv_length(*l);
 
index 8e83ffde755016432450df90eaa0ccc5f21a7675..c95a637b43d811b229b5eddf7328c2970142207a 100644 (file)
@@ -54,6 +54,7 @@ int strv_extend(char ***l, const char *value);
 #if 0 /// UNNEEDED by elogind
 int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
 #endif // 0
+int strv_extend_front(char ***l, const char *value);
 int strv_push(char ***l, char *value);
 int strv_push_pair(char ***l, char *a, char *b);
 int strv_push_prepend(char ***l, char *value);
@@ -76,8 +77,10 @@ bool strv_equal(char **a, char **b);
 char **strv_new(const char *x, ...) _sentinel_;
 char **strv_new_ap(const char *x, va_list ap);
 
+#define STRV_IGNORE ((const char *) -1)
+
 static inline const char* STRV_IFNOTNULL(const char *x) {
-        return x ? x : (const char *) -1;
+        return x ? x : STRV_IGNORE;
 }
 
 static inline bool strv_isempty(char * const *l) {
@@ -90,6 +93,7 @@ char **strv_split_newlines(const char *s);
 
 int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
 #endif // 0
+
 char *strv_join(char **l, const char *separator);
 #if 0 /// UNNEEDED by elogind
 char *strv_join_quoted(char **l);
@@ -102,6 +106,7 @@ int strv_make_nulstr(char **l, char **p, size_t *n);
 
 bool strv_overlap(char **a, char **b) _pure_;
 #endif // 0
+
 #define STRV_FOREACH(s, l)                      \
         for ((s) = (l); (s) && *(s); (s)++)
 
index 75a0d6fd8ee58268e92c6802757eafd07862dbad..0659310a743b92a759c1a1743d8720c746982f0f 100644 (file)
@@ -50,6 +50,7 @@
 #include "socket-util.h"
 #include "stat-util.h"
 #include "string-util.h"
+#include "strv.h"
 #include "terminal-util.h"
 #include "time-util.h"
 #include "util.h"
@@ -155,14 +156,14 @@ int ask_char(char *ret, const char *replies, const char *text, ...) {
                 char c;
                 bool need_nl = true;
 
-                if (on_tty())
+                if (colors_enabled())
                         fputs(ANSI_HIGHLIGHT, stdout);
 
                 va_start(ap, text);
                 vprintf(text, ap);
                 va_end(ap);
 
-                if (on_tty())
+                if (colors_enabled())
                         fputs(ANSI_NORMAL, stdout);
 
                 fflush(stdout);
@@ -199,14 +200,14 @@ int ask_string(char **ret, const char *text, ...) {
                 char line[LINE_MAX];
                 va_list ap;
 
-                if (on_tty())
+                if (colors_enabled())
                         fputs(ANSI_HIGHLIGHT, stdout);
 
                 va_start(ap, text);
                 vprintf(text, ap);
                 va_end(ap);
 
-                if (on_tty())
+                if (colors_enabled())
                         fputs(ANSI_NORMAL, stdout);
 
                 fflush(stdout);
@@ -715,6 +716,64 @@ char *resolve_dev_console(char **active) {
         return tty;
 }
 
+int get_kernel_consoles(char ***consoles) {
+        _cleanup_strv_free_ char **con = NULL;
+        _cleanup_free_ char *line = NULL;
+        const char *active;
+        int r;
+
+        assert(consoles);
+
+        r = read_one_line_file("/sys/class/tty/console/active", &line);
+        if (r < 0)
+                return r;
+
+        active = line;
+        for (;;) {
+                _cleanup_free_ char *tty = NULL;
+                char *path;
+
+                r = extract_first_word(&active, &tty, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                if (streq(tty, "tty0")) {
+                        tty = mfree(tty);
+                        r = read_one_line_file("/sys/class/tty/tty0/active", &tty);
+                        if (r < 0)
+                                return r;
+                }
+
+                path = strappend("/dev/", tty);
+                if (!path)
+                        return -ENOMEM;
+
+                if (access(path, F_OK) < 0) {
+                        log_debug_errno(errno, "Console device %s is not accessible, skipping: %m", path);
+                        free(path);
+                        continue;
+                }
+
+                r = strv_consume(&con, path);
+                if (r < 0)
+                        return r;
+        }
+
+        if (strv_isempty(con)) {
+                log_debug("No devices found for system console");
+
+                r = strv_extend(&con, "/dev/console");
+                if (r < 0)
+                        return r;
+        }
+
+        *consoles = con;
+        con = NULL;
+        return 0;
+}
+
 bool tty_is_vc_resolve(const char *tty) {
         _cleanup_free_ char *active = NULL;
 
@@ -839,9 +898,7 @@ int make_stdio(int fd) {
 
         /* Explicitly unset O_CLOEXEC, since if fd was < 3, then
          * dup2() was a NOP and the bit hence possibly set. */
-        fd_cloexec(STDIN_FILENO, false);
-        fd_cloexec(STDOUT_FILENO, false);
-        fd_cloexec(STDERR_FILENO, false);
+        stdio_unset_cloexec();
 
         return 0;
 }
@@ -856,7 +913,6 @@ int make_null_stdio(void) {
         return make_stdio(null_fd);
 }
 
-#if 0 /// UNNEEDED by elogind
 int getttyname_malloc(int fd, char **ret) {
         size_t l = 100;
         int r;
@@ -906,7 +962,6 @@ int getttyname_harder(int fd, char **r) {
         *r = s;
         return 0;
 }
-#endif // 0
 
 int get_ctty_devnr(pid_t pid, dev_t *d) {
         int r;
@@ -1148,15 +1203,38 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
 }
 #endif // 0
 
+static bool getenv_terminal_is_dumb(void) {
+        const char *e;
+
+        e = getenv("TERM");
+        if (!e)
+                return true;
+
+        return streq(e, "dumb");
+}
+
+bool terminal_is_dumb(void) {
+        if (!on_tty())
+                return true;
+
+        return getenv_terminal_is_dumb();
+}
+
 bool colors_enabled(void) {
-        const char *colors;
+        static int enabled = -1;
 
-        colors = getenv("SYSTEMD_COLORS");
-        if (!colors) {
-                if (streq_ptr(getenv("TERM"), "dumb"))
-                        return false;
-                return on_tty();
+        if (_unlikely_(enabled < 0)) {
+                const char *colors;
+
+                colors = getenv("SYSTEMD_COLORS");
+                if (colors)
+                        enabled = parse_boolean(colors) != 0;
+                else if (getpid() == 1)
+                        /* PID1 outputs to the console without holding it open all the time */
+                        enabled = !getenv_terminal_is_dumb();
+                else
+                        enabled = !terminal_is_dumb();
         }
 
-        return parse_boolean(colors) != 0;
+        return enabled;
 }
index 2296632d1e389d82cec6afa21aa720aa128fabe7..561045871eae411c6c877b6f828dc7d6f92b815a 100644 (file)
@@ -68,6 +68,7 @@ int vt_disallocate(const char *name);
 
 char *resolve_dev_console(char **active);
 #endif // 0
+int get_kernel_consoles(char ***consoles);
 bool tty_is_vc(const char *tty);
 #if 0 /// UNNEEDED by elogind
 bool tty_is_vc_resolve(const char *tty);
@@ -93,6 +94,7 @@ void columns_lines_cache_reset(int _unused_ signum);
 #endif // 0
 
 bool on_tty(void);
+bool terminal_is_dumb(void);
 bool colors_enabled(void);
 
 static inline const char *ansi_underline(void) {
@@ -130,10 +132,10 @@ static inline const char *ansi_normal(void) {
 int get_ctty_devnr(pid_t pid, dev_t *d);
 int get_ctty(pid_t, dev_t *_devnr, char **r);
 
-#if 0 /// UNNEEDED by elogind
 int getttyname_malloc(int fd, char **r);
 int getttyname_harder(int fd, char **r);
 
+#if 0 /// UNNEEDED by elogind
 int ptsname_malloc(int fd, char **ret);
 int ptsname_namespace(int pty, char **ret);
 
index 98ec92918697f0c6600abe0ba150d67dbf4dbe64..1c4999aae65d9f3cddcd0bce6792a95b5cfbeb0c 100644 (file)
 static nsec_t timespec_load_nsec(const struct timespec *ts);
 #endif // 0
 
+static clockid_t map_clock_id(clockid_t c) {
+
+        /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will
+         * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is
+         * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on
+         * those archs. */
+
+        switch (c) {
+
+        case CLOCK_BOOTTIME_ALARM:
+                return CLOCK_BOOTTIME;
+
+        case CLOCK_REALTIME_ALARM:
+                return CLOCK_REALTIME;
+
+        default:
+                return c;
+        }
+}
+
 usec_t now(clockid_t clock_id) {
         struct timespec ts;
 
-        assert_se(clock_gettime(clock_id, &ts) == 0);
+        assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0);
 
         return timespec_load(&ts);
 }
@@ -56,7 +76,7 @@ usec_t now(clockid_t clock_id) {
 nsec_t now_nsec(clockid_t clock_id) {
         struct timespec ts;
 
-        assert_se(clock_gettime(clock_id, &ts) == 0);
+        assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0);
 
         return timespec_load_nsec(&ts);
 }
@@ -71,6 +91,16 @@ dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
         return ts;
 }
 
+triple_timestamp* triple_timestamp_get(triple_timestamp *ts) {
+        assert(ts);
+
+        ts->realtime = now(CLOCK_REALTIME);
+        ts->monotonic = now(CLOCK_MONOTONIC);
+        ts->boottime = clock_boottime_supported() ? now(CLOCK_BOOTTIME) : USEC_INFINITY;
+
+        return ts;
+}
+
 dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
         int64_t delta;
         assert(ts);
@@ -89,6 +119,24 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
 }
 
 #if 0 /// UNNEEDED by elogind
+triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) {
+        int64_t delta;
+
+        assert(ts);
+
+        if (u == USEC_INFINITY || u <= 0) {
+                ts->realtime = ts->monotonic = ts->boottime = u;
+                return ts;
+        }
+
+        ts->realtime = u;
+        delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
+        ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
+        ts->boottime = clock_boottime_supported() ? usec_sub(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
+
+        return ts;
+}
+
 dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
         int64_t delta;
         assert(ts);
@@ -122,11 +170,30 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
 }
 #endif // 0
 
+usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) {
+
+        switch (clock) {
+
+        case CLOCK_REALTIME:
+        case CLOCK_REALTIME_ALARM:
+                return ts->realtime;
+
+        case CLOCK_MONOTONIC:
+                return ts->monotonic;
+
+        case CLOCK_BOOTTIME:
+        case CLOCK_BOOTTIME_ALARM:
+                return ts->boottime;
+
+        default:
+                return USEC_INFINITY;
+        }
+}
+
 usec_t timespec_load(const struct timespec *ts) {
         assert(ts);
 
-        if (ts->tv_sec == (time_t) -1 &&
-            ts->tv_nsec == (long) -1)
+        if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
                 return USEC_INFINITY;
 
         if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
@@ -141,13 +208,13 @@ usec_t timespec_load(const struct timespec *ts) {
 static nsec_t timespec_load_nsec(const struct timespec *ts) {
         assert(ts);
 
-        if (ts->tv_sec == (time_t) -1 &&
-            ts->tv_nsec == (long) -1)
+        if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
                 return NSEC_INFINITY;
 
-        return
-                (nsec_t) ts->tv_sec * NSEC_PER_SEC +
-                (nsec_t) ts->tv_nsec;
+        if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC)
+                return NSEC_INFINITY;
+
+        return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec;
 }
 #endif // 0
 
@@ -314,15 +381,15 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
                 const char *suffix;
                 usec_t usec;
         } table[] = {
-                { "y", USEC_PER_YEAR },
-                { "month", USEC_PER_MONTH },
-                { "w", USEC_PER_WEEK },
-                { "d", USEC_PER_DAY },
-                { "h", USEC_PER_HOUR },
-                { "min", USEC_PER_MINUTE },
-                { "s", USEC_PER_SEC },
-                { "ms", USEC_PER_MSEC },
-                { "us", 1 },
+                { "y",     USEC_PER_YEAR   },
+                { "month", USEC_PER_MONTH  },
+                { "w",     USEC_PER_WEEK   },
+                { "d",     USEC_PER_DAY    },
+                { "h",     USEC_PER_HOUR   },
+                { "min",   USEC_PER_MINUTE },
+                { "s",     USEC_PER_SEC    },
+                { "ms",    USEC_PER_MSEC   },
+                { "us",    1               },
         };
 
         unsigned i;
@@ -442,7 +509,7 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
         assert(t);
 
         if (sscanf(value, "%llu %llu", &a, &b) != 2) {
-                log_debug("Failed to parse finish timestamp value %s.", value);
+                log_debug("Failed to parse dual timestamp value \"%s\": %m", value);
                 return -EINVAL;
         }
 
@@ -452,6 +519,20 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
         return 0;
 }
 
+#endif // 0
+int timestamp_deserialize(const char *value, usec_t *timestamp) {
+        int r;
+
+        assert(value);
+
+        r = safe_atou64(value, timestamp);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to parse timestamp value \"%s\": %m", value);
+
+        return r;
+}
+
+#if 0 /// UNNEEDED by elogind
 int parse_timestamp(const char *t, usec_t *usec) {
         static const struct {
                 const char *name;
@@ -558,12 +639,12 @@ int parse_timestamp(const char *t, usec_t *usec) {
                 goto from_tm;
 
         } else if (streq(t, "yesterday")) {
-                tm.tm_mday --;
+                tm.tm_mday--;
                 tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                 goto from_tm;
 
         } else if (streq(t, "tomorrow")) {
-                tm.tm_mday ++;
+                tm.tm_mday++;
                 tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                 goto from_tm;
         }
@@ -687,42 +768,56 @@ finish:
 }
 #endif // 0
 
-int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
-
+static char* extract_multiplier(char *p, usec_t *multiplier) {
         static const struct {
                 const char *suffix;
                 usec_t usec;
         } table[] = {
-                { "seconds", USEC_PER_SEC },
-                { "second", USEC_PER_SEC },
-                { "sec", USEC_PER_SEC },
-                { "s", USEC_PER_SEC },
+                { "seconds", USEC_PER_SEC    },
+                { "second",  USEC_PER_SEC    },
+                { "sec",     USEC_PER_SEC    },
+                { "s",       USEC_PER_SEC    },
                 { "minutes", USEC_PER_MINUTE },
-                { "minute", USEC_PER_MINUTE },
-                { "min", USEC_PER_MINUTE },
-                { "months", USEC_PER_MONTH },
-                { "month", USEC_PER_MONTH },
+                { "minute",  USEC_PER_MINUTE },
+                { "min",     USEC_PER_MINUTE },
+                { "months",  USEC_PER_MONTH  },
+                { "month",   USEC_PER_MONTH  },
                 { "M",       USEC_PER_MONTH  },
-                { "msec", USEC_PER_MSEC },
-                { "ms", USEC_PER_MSEC },
-                { "m", USEC_PER_MINUTE },
-                { "hours", USEC_PER_HOUR },
-                { "hour", USEC_PER_HOUR },
-                { "hr", USEC_PER_HOUR },
-                { "h", USEC_PER_HOUR },
-                { "days", USEC_PER_DAY },
-                { "day", USEC_PER_DAY },
-                { "d", USEC_PER_DAY },
-                { "weeks", USEC_PER_WEEK },
-                { "week", USEC_PER_WEEK },
-                { "w", USEC_PER_WEEK },
-                { "years", USEC_PER_YEAR },
-                { "year", USEC_PER_YEAR },
-                { "y", USEC_PER_YEAR },
-                { "usec", 1ULL },
-                { "us", 1ULL },
+                { "msec",    USEC_PER_MSEC   },
+                { "ms",      USEC_PER_MSEC   },
+                { "m",       USEC_PER_MINUTE },
+                { "hours",   USEC_PER_HOUR   },
+                { "hour",    USEC_PER_HOUR   },
+                { "hr",      USEC_PER_HOUR   },
+                { "h",       USEC_PER_HOUR   },
+                { "days",    USEC_PER_DAY    },
+                { "day",     USEC_PER_DAY    },
+                { "d",       USEC_PER_DAY    },
+                { "weeks",   USEC_PER_WEEK   },
+                { "week",    USEC_PER_WEEK   },
+                { "w",       USEC_PER_WEEK   },
+                { "years",   USEC_PER_YEAR   },
+                { "year",    USEC_PER_YEAR   },
+                { "y",       USEC_PER_YEAR   },
+                { "usec",    1ULL            },
+                { "us",      1ULL            },
         };
+        unsigned i;
 
+        for (i = 0; i < ELEMENTSOF(table); i++) {
+                char *e;
+
+                e = startswith(p, table[i].suffix);
+                if (e) {
+                        *multiplier = table[i].usec;
+                        return e;
+                }
+        }
+
+        return p;
+}
+
+int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
         const char *p, *s;
         usec_t r = 0;
         bool something = false;
@@ -747,8 +842,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
         for (;;) {
                 long long l, z = 0;
                 char *e;
-                unsigned i, n = 0;
-                usec_t multiplier, k;
+                unsigned n = 0;
+                usec_t multiplier = default_unit, k;
 
                 p += strspn(p, WHITESPACE);
 
@@ -761,10 +856,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
 
                 errno = 0;
                 l = strtoll(p, &e, 10);
-
                 if (errno > 0)
                         return -errno;
-
                 if (l < 0)
                         return -ERANGE;
 
@@ -788,18 +881,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
                         return -EINVAL;
 
                 e += strspn(e, WHITESPACE);
-
-                for (i = 0; i < ELEMENTSOF(table); i++)
-                        if (startswith(e, table[i].suffix)) {
-                                multiplier = table[i].usec;
-                                p = e + strlen(table[i].suffix);
-                                break;
-                        }
-
-                if (i >= ELEMENTSOF(table)) {
-                        multiplier = default_unit;
-                        p = e;
-                }
+                p = extract_multiplier(e, &multiplier);
 
                 something = true;
 
@@ -1063,24 +1145,61 @@ bool timezone_is_valid(const char *name) {
         return true;
 }
 
-clockid_t clock_boottime_or_monotonic(void) {
-        static clockid_t clock = -1;
-        int fd;
-
-        if (clock != -1)
-                return clock;
-
-        fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
-        if (fd < 0)
-                clock = CLOCK_MONOTONIC;
-        else {
-                safe_close(fd);
-                clock = CLOCK_BOOTTIME;
+#endif // 0
+bool clock_boottime_supported(void) {
+        static int supported = -1;
+
+        /* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */
+
+        if (supported < 0) {
+                int fd;
+
+                fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+                if (fd < 0)
+                        supported = false;
+                else {
+                        safe_close(fd);
+                        supported = true;
+                }
         }
 
-        return clock;
+        return supported;
 }
 
+#if 0 /// UNNEEDED by elogind
+clockid_t clock_boottime_or_monotonic(void) {
+        if (clock_boottime_supported())
+                return CLOCK_BOOTTIME;
+        else
+                return CLOCK_MONOTONIC;
+}
+#endif // 0
+
+bool clock_supported(clockid_t clock) {
+        struct timespec ts;
+
+        switch (clock) {
+
+        case CLOCK_MONOTONIC:
+        case CLOCK_REALTIME:
+                return true;
+
+        case CLOCK_BOOTTIME:
+                return clock_boottime_supported();
+
+        case CLOCK_BOOTTIME_ALARM:
+                if (!clock_boottime_supported())
+                        return false;
+
+                /* fall through, after checking the cached value for CLOCK_BOOTTIME. */
+
+        default:
+                /* For everything else, check properly */
+                return clock_gettime(clock, &ts) >= 0;
+        }
+}
+
+#if 0 /// UNNEEDED by elogind
 int get_timezone(char **tz) {
         _cleanup_free_ char *t = NULL;
         const char *e;
index 3c3fcca57f39edf253402cde58f3c5476aab0e6f..f80b6594f54b7779c35e03e0497e55360f5fddc9 100644 (file)
@@ -39,6 +39,12 @@ typedef struct dual_timestamp {
         usec_t monotonic;
 } dual_timestamp;
 
+typedef struct triple_timestamp {
+        usec_t realtime;
+        usec_t monotonic;
+        usec_t boottime;
+} triple_timestamp;
+
 #define USEC_INFINITY ((usec_t) -1)
 #define NSEC_INFINITY ((nsec_t) -1)
 
@@ -69,7 +75,8 @@ typedef struct dual_timestamp {
 
 #define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
 
-#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL })
+#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {})
+#define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {})
 
 usec_t now(clockid_t clock);
 #if 0 /// UNNEEDED by elogind
@@ -83,11 +90,28 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
 dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u);
 #endif // 0
 
+triple_timestamp* triple_timestamp_get(triple_timestamp *ts);
+triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u);
+
+#define DUAL_TIMESTAMP_HAS_CLOCK(clock)                               \
+        IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC)
+
+#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock)                               \
+        IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
+
 static inline bool dual_timestamp_is_set(dual_timestamp *ts) {
         return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
                 (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY));
 }
 
+static inline bool triple_timestamp_is_set(triple_timestamp *ts) {
+        return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
+                (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) ||
+                (ts->boottime > 0 && ts->boottime != USEC_INFINITY));
+}
+
+usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
+
 usec_t timespec_load(const struct timespec *ts) _pure_;
 struct timespec *timespec_store(struct timespec *ts, usec_t u);
 
@@ -108,7 +132,10 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
 #if 0 /// UNNEEDED by elogind
 void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
 int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
+#endif // 0
+int timestamp_deserialize(const char *value, usec_t *timestamp);
 
+#if 0 /// UNNEEDED by elogind
 int parse_timestamp(const char *t, usec_t *usec);
 #endif // 0
 
@@ -122,6 +149,10 @@ bool ntp_synced(void);
 int get_timezones(char ***l);
 bool timezone_is_valid(const char *name);
 
+#endif // 0
+bool clock_boottime_supported(void);
+bool clock_supported(clockid_t clock);
+#if 0 /// UNNEEDED by elogind
 clockid_t clock_boottime_or_monotonic(void);
 #endif // 0
 
index be90d5a3cb9188bba95d3e9ae891bc8e983bcf1e..359d87d27c2b4f70c667f1c666afc19f997ca04d 100644 (file)
@@ -31,7 +31,6 @@ static inline void umaskp(mode_t *u) {
 
 #define _cleanup_umask_ _cleanup_(umaskp)
 
-#if 0 /// UNNEEDED by elogind
 struct _umask_struct_ {
         mode_t mask;
         bool quit;
@@ -45,4 +44,3 @@ static inline void _reset_umask_(struct _umask_struct_ *s) {
         for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
              !_saved_umask_.quit ;                                      \
              _saved_umask_.quit = true)
-#endif // 0
index 79be645bedcab03410a35152379c892dad6d98f3..7c847a3ccb8884f4bcb1430efdd3781a8ebdcb81 100644 (file)
@@ -109,3 +109,21 @@ static inline void unaligned_write_le64(void *_u, uint64_t a) {
         unaligned_write_le32(u, (uint32_t) a);
         unaligned_write_le32(u + 4, (uint32_t) (a >> 32));
 }
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define unaligned_read_ne16 unaligned_read_be16
+#define unaligned_read_ne32 unaligned_read_be32
+#define unaligned_read_ne64 unaligned_read_be64
+
+#define unaligned_write_ne16 unaligned_write_be16
+#define unaligned_write_ne32 unaligned_write_be32
+#define unaligned_write_ne64 unaligned_write_be64
+#else
+#define unaligned_read_ne16 unaligned_read_le16
+#define unaligned_read_ne32 unaligned_read_le32
+#define unaligned_read_ne64 unaligned_read_le64
+
+#define unaligned_write_ne16 unaligned_write_le16
+#define unaligned_write_ne32 unaligned_write_le32
+#define unaligned_write_ne64 unaligned_write_le64
+#endif
index 6e6bd3bdb8aaee0642e51e8d755b0ad1cbdb0967..463301eebffdac579a9ebe3d1a978f7071b620bb 100644 (file)
@@ -761,7 +761,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
         else {
                 r = free_and_strdup(&s, "-.slice");
                 if (r < 0) {
-                free(s);
+                        free(s);
                         return r;
                 }
         }
index 94985654f89c208bcb189e83608be57d9c5c2980..5b70f18bed766cc1bc72779bec1399334255055f 100644 (file)
@@ -196,7 +196,6 @@ typedef enum SwapState {
         _SWAP_STATE_INVALID = -1
 } SwapState;
 
-
 typedef enum TargetState {
         TARGET_DEAD,
         TARGET_ACTIVE,
index 006a73e59ad24ab75311a91fa97217d45c895633..fbe9f2a969987f86b225bd3a170173c0698aa7d5 100644 (file)
@@ -30,6 +30,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include "missing.h"
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "formats-util.h"
@@ -75,7 +76,6 @@ int parse_uid(const char *s, uid_t *ret) {
         return 0;
 }
 
-#if 0 /// UNNEEDED by elogind
 char* getlogname_malloc(void) {
         uid_t uid;
         struct stat st;
@@ -88,6 +88,7 @@ char* getlogname_malloc(void) {
         return uid_to_name(uid);
 }
 
+#if 0 /// UNNEEDED by elogind
 char *getusername_malloc(void) {
         const char *e;
 
@@ -462,7 +463,7 @@ int take_etc_passwd_lock(const char *root) {
          *
          * Note that shadow-utils also takes per-database locks in
          * addition to lckpwdf(). However, we don't given that they
-         * are redundant as they they invoke lckpwdf() first and keep
+         * are redundant as they invoke lckpwdf() first and keep
          * it during everything they do. The per-database locks are
          * awfully racy, and thus we just won't do them. */
 
index 8e652584d206e27e5c1a03d4b6455128bdc3899b..5d1d0abe4d1c960f12eda860335bd90453193e0b 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <stdbool.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 bool uid_is_valid(uid_t uid);
 
@@ -34,8 +35,8 @@ static inline int parse_gid(const char *s, gid_t *ret_gid) {
         return parse_uid(s, (uid_t*) ret_gid);
 }
 
-#if 0 /// UNNEEDED by elogind
 char* getlogname_malloc(void);
+#if 0 /// UNNEEDED by elogind
 char* getusername_malloc(void);
 #endif // 0
 
@@ -69,3 +70,7 @@ int take_etc_passwd_lock(const char *root);
 
 #define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1))
 #define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
+
+static inline bool userns_supported(void) {
+        return access("/proc/self/uid_map", F_OK) >= 0;
+}
index 629db123cdda8a8e5a1408ce2d9ce935ae260ee1..6eae2b983d8dfd7943c479be9918d8539fd538fd 100644 (file)
@@ -241,7 +241,7 @@ char *utf8_escape_non_printable(const char *str) {
                                         *(s++) = hexchar((int) *str);
 
                                         str += 1;
-                                        len --;
+                                        len--;
                                 }
                         }
                 } else {
index 12c272d66e357da28c4e7fea9105cf1ac4fc4b7f..f9b9c9468bb1581bd12668a3ad5c12afdf12b236 100644 (file)
@@ -28,6 +28,7 @@
 #include "missing.h"
 
 #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
+#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf"
 
 bool unichar_is_valid(char32_t c);
 
index 8f2317f2852906c81cd21991ffbed22ae3593927..f14dba9d9144e31abcd9f4a44446aac1eb060ffb 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "alloc-util.h"
 #include "build.h"
+#include "cgroup-util.h"
 //#include "def.h"
 #include "dirent-util.h"
 #include "fd-util.h"
@@ -55,6 +56,7 @@
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
+#include "umask-util.h"
 #include "user-util.h"
 #include "util.h"
 
@@ -63,6 +65,7 @@ assert_cc(EAGAIN == EWOULDBLOCK);
 
 int saved_argc = 0;
 char **saved_argv = NULL;
+static int saved_in_initrd = -1;
 
 size_t page_size(void) {
         static thread_local size_t pgsz = 0;
@@ -423,13 +426,17 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
                         _exit(EXIT_FAILURE);
                 }
 
-                if (!stdout_is_tty)
-                        dup2(fd, STDOUT_FILENO);
+                if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
+                        log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
+                        _exit(EXIT_FAILURE);
+                }
 
-                if (!stderr_is_tty)
-                        dup2(fd, STDERR_FILENO);
+                if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
+                        log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
+                        _exit(EXIT_FAILURE);
+                }
 
-                if (fd > 2)
+                if (fd > STDERR_FILENO)
                         close(fd);
         }
 
@@ -453,11 +460,10 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
 }
 
 bool in_initrd(void) {
-        static int saved = -1;
         struct statfs s;
 
-        if (saved >= 0)
-                return saved;
+        if (saved_in_initrd >= 0)
+                return saved_in_initrd;
 
         /* We make two checks here:
          *
@@ -469,11 +475,15 @@ bool in_initrd(void) {
          * emptying when transititioning to the main systemd.
          */
 
-        saved = access("/etc/initrd-release", F_OK) >= 0 &&
-                statfs("/", &s) >= 0 &&
-                is_temporary_fs(&s);
+        saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
+                          statfs("/", &s) >= 0 &&
+                          is_temporary_fs(&s);
 
-        return saved;
+        return saved_in_initrd;
+}
+
+void in_initrd_force(bool value) {
+        saved_in_initrd = value;
 }
 
 #if 0 /// UNNEEDED by elogind
@@ -522,7 +532,7 @@ int on_ac_power(void) {
                 if (!de)
                         break;
 
-                if (hidden_file(de->d_name))
+                if (hidden_or_backup_file(de->d_name))
                         continue;
 
                 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
@@ -576,48 +586,7 @@ int on_ac_power(void) {
         return found_online || !found_offline;
 }
 
-bool id128_is_valid(const char *s) {
-        size_t i, l;
-
-        l = strlen(s);
-        if (l == 32) {
-
-                /* Simple formatted 128bit hex string */
-
-                for (i = 0; i < l; i++) {
-                        char c = s[i];
-
-                        if (!(c >= '0' && c <= '9') &&
-                            !(c >= 'a' && c <= 'z') &&
-                            !(c >= 'A' && c <= 'Z'))
-                                return false;
-                }
-
-        } else if (l == 36) {
-
-                /* Formatted UUID */
-
-                for (i = 0; i < l; i++) {
-                        char c = s[i];
-
-                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
-                                if (c != '-')
-                                        return false;
-                        } else {
-                                if (!(c >= '0' && c <= '9') &&
-                                    !(c >= 'a' && c <= 'z') &&
-                                    !(c >= 'A' && c <= 'Z'))
-                                        return false;
-                        }
-                }
-
-        } else
-                return false;
-
-        return true;
-}
 #endif // 0
-
 int container_get_leader(const char *machine, pid_t *pid) {
         _cleanup_free_ char *s = NULL, *class = NULL;
         const char *p;
@@ -768,27 +737,141 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
 }
 
 uint64_t physical_memory(void) {
-        long mem;
+        _cleanup_free_ char *root = NULL, *value = NULL;
+        uint64_t mem, lim;
+        size_t ps;
+        long sc;
+
+        /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
+         * memory.
+         *
+         * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
+         * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
+
+        sc = sysconf(_SC_PHYS_PAGES);
+        assert(sc > 0);
+
+        ps = page_size();
+        mem = (uint64_t) sc * (uint64_t) ps;
 
-        /* We return this as uint64_t in case we are running as 32bit
-         * process on a 64bit kernel with huge amounts of memory */
+        if (cg_get_root_path(&root) < 0)
+                return mem;
 
-        mem = sysconf(_SC_PHYS_PAGES);
-        assert(mem > 0);
+        if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
+                return mem;
 
-        return (uint64_t) mem * (uint64_t) page_size();
+        if (safe_atou64(value, &lim) < 0)
+                return mem;
+
+        /* Make sure the limit is a multiple of our own page size */
+        lim /= ps;
+        lim *= ps;
+
+        return MIN(mem, lim);
+}
+
+uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
+        uint64_t p, m, ps, r;
+
+        assert(max > 0);
+
+        /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
+         * the result is a multiple of the page size (rounds down). */
+
+        ps = page_size();
+        assert(ps > 0);
+
+        p = physical_memory() / ps;
+        assert(p > 0);
+
+        m = p * v;
+        if (m / p != v)
+                return UINT64_MAX;
+
+        m /= max;
+
+        r = m * ps;
+        if (r / ps != m)
+                return UINT64_MAX;
+
+        return r;
+}
+
+uint64_t system_tasks_max(void) {
+
+#if SIZEOF_PID_T == 4
+#define TASKS_MAX ((uint64_t) (INT32_MAX-1))
+#elif SIZEOF_PID_T == 2
+#define TASKS_MAX ((uint64_t) (INT16_MAX-1))
+#else
+#error "Unknown pid_t size"
+#endif
+
+        _cleanup_free_ char *value = NULL, *root = NULL;
+        uint64_t a = TASKS_MAX, b = TASKS_MAX;
+
+        /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
+         * limit:
+         *
+         * a) the maximum value for the pid_t type
+         * b) the cgroups pids_max attribute for the system
+         * c) the kernel's configure maximum PID value
+         *
+         * And then pick the smallest of the three */
+
+        if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
+                (void) safe_atou64(value, &a);
+
+        if (cg_get_root_path(&root) >= 0) {
+                value = mfree(value);
+
+                if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
+                        (void) safe_atou64(value, &b);
+        }
+
+        return MIN3(TASKS_MAX,
+                    a <= 0 ? TASKS_MAX : a,
+                    b <= 0 ? TASKS_MAX : b);
+}
+
+uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
+        uint64_t t, m;
+
+        assert(max > 0);
+
+        /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
+         * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
+
+        t = system_tasks_max();
+        assert(t > 0);
+
+        m = t * v;
+        if (m / t != v) /* overflow? */
+                return UINT64_MAX;
+
+        return m / max;
 }
 
 #if 0 /// UNNEEDED by elogind
-int update_reboot_param_file(const char *param) {
-        int r = 0;
+int update_reboot_parameter_and_warn(const char *param) {
+        int r;
 
-        if (param) {
-                r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
+        if (isempty(param)) {
+                if (unlink("/run/systemd/reboot-param") < 0) {
+                        if (errno == ENOENT)
+                                return 0;
+
+                        return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m");
+                }
+
+                return 0;
+        }
+
+        RUN_WITH_UMASK(0022) {
+                r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
-        } else
-                (void) unlink(REBOOT_PARAM_FILE);
+                        return log_warning_errno(r, "Failed to write reboot parameter file: %m");
+        }
 
         return 0;
 }
index 179505de8588482b14e13a866d46956e4eecb907..346221ca0c99682f055db0374d1215b05149dd41 100644 (file)
@@ -36,6 +36,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/statfs.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
@@ -91,6 +92,7 @@ int prot_from_flags(int flags) _const_;
 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
 
 bool in_initrd(void);
+void in_initrd_force(bool value);
 
 #if 0 /// UNNEEDED by elogind
 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
@@ -110,6 +112,16 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_
         qsort(base, nmemb, size, compar);
 }
 
+/**
+ * Normal memcpy requires src to be nonnull. We do nothing if n is 0.
+ */
+static inline void memcpy_safe(void *dst, const void *src, size_t n) {
+        if (n == 0)
+                return;
+        assert(src);
+        memcpy(dst, src, n);
+}
+
 #if 0 /// UNNEEDED by elogind
 int on_ac_power(void);
 #endif // 0
@@ -128,7 +140,6 @@ static inline void _reset_errno_(int *saved_errno) {
 
 #define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno
 
-#if 0 /// UNNEEDED by elogind
 static inline int negative_errno(void) {
         /* This helper should be used to shut up gcc if you know 'errno' is
          * negative. Instead of "return -errno;", use "return negative_errno();"
@@ -137,7 +148,6 @@ static inline int negative_errno(void) {
         assert_return(errno > 0, -EINVAL);
         return -errno;
 }
-#endif // 0
 
 static inline unsigned u64log2(uint64_t n) {
 #if __SIZEOF_LONG_LONG__ == 8
@@ -177,18 +187,20 @@ static inline unsigned log2u_round_up(unsigned x) {
 }
 
 #if 0 /// UNNEEDED by elogind
-bool id128_is_valid(const char *s) _pure_;
 #endif // 0
-
 int container_get_leader(const char *machine, pid_t *pid);
 
 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
 
 uint64_t physical_memory(void);
+uint64_t physical_memory_scale(uint64_t v, uint64_t max);
+
+uint64_t system_tasks_max(void);
+uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
 
 #if 0 /// UNNEEDED by elogind
-int update_reboot_param_file(const char *param);
 #endif // 0
+int update_reboot_parameter_and_warn(const char *param);
 
 int version(void);
index 6eb1d0c46e41730f3f1015ed286c4313e2149a7b..0c08201035b815eec3835cc98c442c6e26597925 100644 (file)
@@ -99,6 +99,8 @@ static int detect_vm_cpuid(void) {
                         : "0" (eax)
                 );
 
+                log_debug("Virtualization found, CPUID=%s", sig.text);
+
                 for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
                         if (streq(sig.text, cpuid_vendor_table[j].cpuid))
                                 return cpuid_vendor_table[j].id;
@@ -106,6 +108,7 @@ static int detect_vm_cpuid(void) {
                 return VIRTUALIZATION_VM_OTHER;
         }
 #endif
+        log_debug("No virtualization found in CPUID");
 
         return VIRTUALIZATION_NONE;
 }
@@ -122,19 +125,25 @@ static int detect_vm_device_tree(void) {
 
                 dir = opendir("/proc/device-tree");
                 if (!dir) {
-                        if (errno == ENOENT)
+                        if (errno == ENOENT) {
+                                log_debug_errno(errno, "/proc/device-tree: %m");
                                 return VIRTUALIZATION_NONE;
+                        }
                         return -errno;
                 }
 
                 FOREACH_DIRENT(dent, dir, return -errno)
-                        if (strstr(dent->d_name, "fw-cfg"))
+                        if (strstr(dent->d_name, "fw-cfg")) {
+                                log_debug("Virtualization QEMU: \"fw-cfg\" present in /proc/device-tree/%s", dent->d_name);
                                 return VIRTUALIZATION_QEMU;
+                        }
 
+                log_debug("No virtualization found in /proc/device-tree/*");
                 return VIRTUALIZATION_NONE;
         } else if (r < 0)
                 return r;
 
+        log_debug("Virtualization %s found in /proc/device-tree/hypervisor/compatible", hvtype);
         if (streq(hvtype, "linux,kvm"))
                 return VIRTUALIZATION_KVM;
         else if (strstr(hvtype, "xen"))
@@ -142,6 +151,7 @@ static int detect_vm_device_tree(void) {
         else
                 return VIRTUALIZATION_VM_OTHER;
 #else
+        log_debug("This platform does not support /proc/device-tree");
         return VIRTUALIZATION_NONE;
 #endif
 }
@@ -180,47 +190,77 @@ static int detect_vm_dmi(void) {
                 r = read_one_line_file(dmi_vendors[i], &s);
                 if (r < 0) {
                         if (r == -ENOENT)
-                        continue;
+                                continue;
 
                         return r;
-                        }
+                }
+
+
 
                 for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
-                        if (startswith(s, dmi_vendor_table[j].vendor))
+                        if (startswith(s, dmi_vendor_table[j].vendor)) {
+                                log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]);
                                 return dmi_vendor_table[j].id;
+                        }
         }
 #endif
 
+        log_debug("No virtualization found in DMI");
+
         return VIRTUALIZATION_NONE;
 }
 
 static int detect_vm_xen(void) {
+        /* Check for Dom0 will be executed later in detect_vm_xen_dom0
+           Thats why we dont check the content of /proc/xen/capabilities here. */
+        if (access("/proc/xen/capabilities", F_OK) < 0) {
+                log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+                return VIRTUALIZATION_NONE;
+        }
+
+        log_debug("Virtualization XEN found (/proc/xen/capabilities exists)");
+        return  VIRTUALIZATION_XEN;
+
+}
+
+static bool detect_vm_xen_dom0(void) {
         _cleanup_free_ char *domcap = NULL;
         char *cap, *i;
         int r;
 
         r = read_one_line_file("/proc/xen/capabilities", &domcap);
-        if (r == -ENOENT)
-                return VIRTUALIZATION_NONE;
+        if (r == -ENOENT) {
+                log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+                return false;
+        }
+        if (r < 0)
+                return r;
 
         i = domcap;
-                while ((cap = strsep(&i, ",")))
-                        if (streq(cap, "control_d"))
-                                break;
+        while ((cap = strsep(&i, ",")))
+                if (streq(cap, "control_d"))
+                        break;
+        if (!cap) {
+                log_debug("Virtualization XEN DomU found (/proc/xen/capabilites)");
+                return false;
+        }
 
-        return cap ? VIRTUALIZATION_NONE : VIRTUALIZATION_XEN;
-                }
+        log_debug("Virtualization XEN Dom0 ignored (/proc/xen/capabilities)");
+        return true;
+}
 
 static int detect_vm_hypervisor(void) {
-                _cleanup_free_ char *hvtype = NULL;
+        _cleanup_free_ char *hvtype = NULL;
         int r;
 
-                r = read_one_line_file("/sys/hypervisor/type", &hvtype);
+        r = read_one_line_file("/sys/hypervisor/type", &hvtype);
         if (r == -ENOENT)
                 return VIRTUALIZATION_NONE;
         if (r < 0)
                 return r;
 
+        log_debug("Virtualization %s found in /sys/hypervisor/type", hvtype);
+
         if (streq(hvtype, "xen"))
                 return VIRTUALIZATION_XEN;
         else
@@ -235,9 +275,13 @@ static int detect_vm_uml(void) {
         r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
         if (r < 0)
                 return r;
-        if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n"))
+
+        if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
+                log_debug("UML virtualization found in /proc/cpuinfo");
                 return VIRTUALIZATION_UML;
+        }
 
+        log_debug("No virtualization found in /proc/cpuinfo.");
         return VIRTUALIZATION_NONE;
 }
 
@@ -253,14 +297,16 @@ static int detect_vm_zvm(void) {
         if (r < 0)
                 return r;
 
+        log_debug("Virtualization %s found in /proc/sysinfo", t);
         if (streq(t, "z/VM"))
                 return VIRTUALIZATION_ZVM;
         else
                 return VIRTUALIZATION_KVM;
 #else
+        log_debug("This platform does not support /proc/sysinfo");
         return VIRTUALIZATION_NONE;
 #endif
-        }
+}
 
 /* Returns a short identifier for the various VM implementations */
 int detect_vm(void) {
@@ -318,14 +364,21 @@ int detect_vm(void) {
         if (r < 0)
                 return r;
         if (r != VIRTUALIZATION_NONE)
-                        goto finish;
+                goto finish;
 
         r = detect_vm_zvm();
         if (r < 0)
                 return r;
 
 finish:
+        /* x86 xen Dom0 is detected as XEN in hypervisor and maybe others.
+         * In order to detect the Dom0 as not virtualization we need to
+         * double-check it */
+        if (r == VIRTUALIZATION_XEN && detect_vm_xen_dom0())
+                r = VIRTUALIZATION_NONE;
+
         cached_found = r;
+        log_debug("Found VM virtualization %s", virtualization_to_string(r));
         return r;
 }
 #endif // 0
@@ -414,6 +467,7 @@ int detect_container(void) {
         r = VIRTUALIZATION_CONTAINER_OTHER;
 
 finish:
+        log_debug("Found container virtualization %s", virtualization_to_string(r));
         cached_found = r;
         return r;
 }
@@ -423,10 +477,10 @@ int detect_virtualization(void) {
         int r;
 
         r = detect_container();
-        if (r != 0)
-                return r;
+        if (r == 0)
+                r = detect_vm();
 
-        return detect_vm();
+        return r;
 }
 #endif // 0
 
@@ -440,7 +494,6 @@ int running_in_chroot(void) {
         return ret == 0;
 }
 
-#if 0 /// UNNEEDED by elogind
 static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
         [VIRTUALIZATION_NONE] = "none",
         [VIRTUALIZATION_KVM] = "kvm",
@@ -465,4 +518,3 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(virtualization, int);
-#endif // 0
index 22dd815f330a11596b1f71d1d4f9f3b0e0443738..1d88ab9ab681d8bc5bcd7eeaa6fdec2e23f3fd8c 100644 (file)
@@ -72,7 +72,5 @@ int detect_virtualization(void);
 
 int running_in_chroot(void);
 
-#if 0 /// UNNEEDED by elogind
 const char *virtualization_to_string(int v) _const_;
 int virtualization_from_string(const char *s) _pure_;
-#endif // 0
index 85f3d20604c088ea9faf9ab10af42be17c0e7f5c..6b5c5465316328c1d18ff467cdffd531ee3fccbc 100644 (file)
@@ -111,7 +111,7 @@ ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute,
 
         /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
 
-        fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
+        fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
         if (fd < 0)
                 return -errno;
 
index 0b0f4db56d8af92313962e54f11edc8fabb7e222..9fb7e34dd7560da2fbac627e56fcf51e5f3d009d 100644 (file)
 ***/
 
 #include <stdlib.h>
+#include <sys/socket.h>
 
-#include "sd-bus.h"
-#include "bus-util.h"
-#include "musl_missing.h"
+#include "fd-util.h"
 #include "log.h"
+#include "socket-util.h"
+
+/// Additional includes needed by elogind
+#include "musl_missing.h"
 
 int main(int argc, char *argv[]) {
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-        int r;
+
+        static const union sockaddr_union sa = {
+                .un.sun_family = AF_UNIX,
+                .un.sun_path = "/run/systemd/cgroups-agent",
+        };
+
+        _cleanup_close_ int fd = -1;
+        ssize_t n;
+        size_t l;
 
         if (argc != 2) {
                 log_error("Incorrect number of arguments.");
@@ -38,46 +48,22 @@ int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
-#if 0
-        /* We send this event to the private D-Bus socket and then the
-         * system instance will forward this to the system bus. We do
-         * this to avoid an activation loop when we start dbus when we
-         * are called when the dbus service is shut down. */
-
-        r = bus_connect_system_systemd(&bus);
-#else
-        /* Unlike in systemd where this has to use a private socket,
-           since elogind doesn't associate control groups with services
-           and doesn't manage the dbus service, we can just use the
-           system bus.  */
-        r = sd_bus_open_system(&bus);
-#endif // 0
-
-        if (r < 0) {
-#if 0
-                /* If we couldn't connect we assume this was triggered
-                 * while systemd got restarted/transitioned from
-                 * initrd to the system, so let's ignore this */
-                log_debug_errno(r, "Failed to get D-Bus connection: %m");
-#else
-                /* If dbus isn't running or responding, there is nothing
-                 * we can do about it. */
-                log_debug_errno(r, "Failed to open system bus: %m");
-#endif // 0
+        fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+        if (fd < 0) {
+                log_debug_errno(errno, "Failed to allocate socket: %m");
+                return EXIT_FAILURE;
+        }
+
+        l = strlen(argv[1]);
+
+        n = sendto(fd, argv[1], l, 0, &sa.sa, SOCKADDR_UN_LEN(sa.un));
+        if (n < 0) {
+                log_debug_errno(errno, "Failed to send cgroups agent message: %m");
                 return EXIT_FAILURE;
         }
 
-        r = sd_bus_emit_signal(bus,
-                               "/org/freedesktop/elogind/agent",
-                               "org.freedesktop.elogind.Agent",
-                               "Released",
-                               "s", argv[1]);
-        if (r < 0) {
-#if 0
-                log_debug_errno(r, "Failed to send signal message on private connection: %m");
-#else
-                log_debug_errno(r, "Failed to send signal message: %m");
-#endif // 0
+        if ((size_t) n != l) {
+                log_debug("Datagram size mismatch");
                 return EXIT_FAILURE;
         }
 
index 0cff981dffc926bb0cbf0f9c1c6949bfe029d4b7..4702c54a930c948dabaf640861b821f5c623e261 100644 (file)
 //#include "special.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "stdio-util.h"
 
 #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
 
 #if 0 /// UNNEEDED by elogind
+static void cgroup_compat_warn(void) {
+        static bool cgroup_compat_warned = false;
+
+        if (cgroup_compat_warned)
+                return;
+
+        log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. See cgroup-compat debug messages for details.");
+        cgroup_compat_warned = true;
+}
+
+#define log_cgroup_compat(unit, fmt, ...) do {                                  \
+                cgroup_compat_warn();                                           \
+                log_unit_debug(unit, "cgroup-compat: " fmt, ##__VA_ARGS__);     \
+        } while (false)
+
 void cgroup_context_init(CGroupContext *c) {
         assert(c);
 
@@ -46,7 +62,13 @@ void cgroup_context_init(CGroupContext *c) {
         c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
         c->cpu_quota_per_sec_usec = USEC_INFINITY;
 
-        c->memory_limit = (uint64_t) -1;
+        c->memory_high = CGROUP_LIMIT_MAX;
+        c->memory_max = CGROUP_LIMIT_MAX;
+
+        c->memory_limit = CGROUP_LIMIT_MAX;
+
+        c->io_weight = CGROUP_WEIGHT_INVALID;
+        c->startup_io_weight = CGROUP_WEIGHT_INVALID;
 
         c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
         c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
@@ -63,6 +85,24 @@ void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
         free(a);
 }
 
+void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w) {
+        assert(c);
+        assert(w);
+
+        LIST_REMOVE(device_weights, c->io_device_weights, w);
+        free(w->path);
+        free(w);
+}
+
+void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l) {
+        assert(c);
+        assert(l);
+
+        LIST_REMOVE(device_limits, c->io_device_limits, l);
+        free(l->path);
+        free(l);
+}
+
 void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
         assert(c);
         assert(w);
@@ -84,6 +124,12 @@ void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockI
 void cgroup_context_done(CGroupContext *c) {
         assert(c);
 
+        while (c->io_device_weights)
+                cgroup_context_free_io_device_weight(c, c->io_device_weights);
+
+        while (c->io_device_limits)
+                cgroup_context_free_io_device_limit(c, c->io_device_limits);
+
         while (c->blockio_device_weights)
                 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
 
@@ -95,6 +141,8 @@ void cgroup_context_done(CGroupContext *c) {
 }
 
 void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+        CGroupIODeviceLimit *il;
+        CGroupIODeviceWeight *iw;
         CGroupBlockIODeviceBandwidth *b;
         CGroupBlockIODeviceWeight *w;
         CGroupDeviceAllow *a;
@@ -107,27 +155,39 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
 
         fprintf(f,
                 "%sCPUAccounting=%s\n"
+                "%sIOAccounting=%s\n"
                 "%sBlockIOAccounting=%s\n"
                 "%sMemoryAccounting=%s\n"
                 "%sTasksAccounting=%s\n"
                 "%sCPUShares=%" PRIu64 "\n"
                 "%sStartupCPUShares=%" PRIu64 "\n"
                 "%sCPUQuotaPerSecSec=%s\n"
+                "%sIOWeight=%" PRIu64 "\n"
+                "%sStartupIOWeight=%" PRIu64 "\n"
                 "%sBlockIOWeight=%" PRIu64 "\n"
                 "%sStartupBlockIOWeight=%" PRIu64 "\n"
+                "%sMemoryLow=%" PRIu64 "\n"
+                "%sMemoryHigh=%" PRIu64 "\n"
+                "%sMemoryMax=%" PRIu64 "\n"
                 "%sMemoryLimit=%" PRIu64 "\n"
                 "%sTasksMax=%" PRIu64 "\n"
                 "%sDevicePolicy=%s\n"
                 "%sDelegate=%s\n",
                 prefix, yes_no(c->cpu_accounting),
+                prefix, yes_no(c->io_accounting),
                 prefix, yes_no(c->blockio_accounting),
                 prefix, yes_no(c->memory_accounting),
                 prefix, yes_no(c->tasks_accounting),
                 prefix, c->cpu_shares,
                 prefix, c->startup_cpu_shares,
                 prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
+                prefix, c->io_weight,
+                prefix, c->startup_io_weight,
                 prefix, c->blockio_weight,
                 prefix, c->startup_blockio_weight,
+                prefix, c->memory_low,
+                prefix, c->memory_high,
+                prefix, c->memory_max,
                 prefix, c->memory_limit,
                 prefix, c->tasks_max,
                 prefix, cgroup_device_policy_to_string(c->device_policy),
@@ -140,6 +200,27 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                         a->path,
                         a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
 
+        LIST_FOREACH(device_weights, iw, c->io_device_weights)
+                fprintf(f,
+                        "%sIODeviceWeight=%s %" PRIu64,
+                        prefix,
+                        iw->path,
+                        iw->weight);
+
+        LIST_FOREACH(device_limits, il, c->io_device_limits) {
+                char buf[FORMAT_BYTES_MAX];
+                CGroupIOLimitType type;
+
+                for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
+                        if (il->limits[type] != cgroup_io_limit_defaults[type])
+                                fprintf(f,
+                                        "%s%s=%s %s\n",
+                                        prefix,
+                                        cgroup_io_limit_type_to_string(type),
+                                        il->path,
+                                        format_bytes(buf, sizeof(buf), il->limits[type]));
+        }
+
         LIST_FOREACH(device_weights, w, c->blockio_device_weights)
                 fprintf(f,
                         "%sBlockIODeviceWeight=%s %" PRIu64,
@@ -150,16 +231,22 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
                 char buf[FORMAT_BYTES_MAX];
 
-                fprintf(f,
-                        "%s%s=%s %s\n",
-                        prefix,
-                        b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth",
-                        b->path,
-                        format_bytes(buf, sizeof(buf), b->bandwidth));
+                if (b->rbps != CGROUP_LIMIT_MAX)
+                        fprintf(f,
+                                "%sBlockIOReadBandwidth=%s %s\n",
+                                prefix,
+                                b->path,
+                                format_bytes(buf, sizeof(buf), b->rbps));
+                if (b->wbps != CGROUP_LIMIT_MAX)
+                        fprintf(f,
+                                "%sBlockIOWriteBandwidth=%s %s\n",
+                                prefix,
+                                b->path,
+                                format_bytes(buf, sizeof(buf), b->wbps));
         }
 }
 
-static int lookup_blkio_device(const char *p, dev_t *dev) {
+static int lookup_block_device(const char *p, dev_t *dev) {
         struct stat st;
         int r;
 
@@ -296,10 +383,172 @@ fail:
         return -errno;
 }
 
-void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state) {
+static bool cgroup_context_has_io_config(CGroupContext *c) {
+        return c->io_accounting ||
+                c->io_weight != CGROUP_WEIGHT_INVALID ||
+                c->startup_io_weight != CGROUP_WEIGHT_INVALID ||
+                c->io_device_weights ||
+                c->io_device_limits;
+}
+
+static bool cgroup_context_has_blockio_config(CGroupContext *c) {
+        return c->blockio_accounting ||
+                c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
+                c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
+                c->blockio_device_weights ||
+                c->blockio_device_bandwidths;
+}
+
+static uint64_t cgroup_context_io_weight(CGroupContext *c, ManagerState state) {
+        if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
+            c->startup_io_weight != CGROUP_WEIGHT_INVALID)
+                return c->startup_io_weight;
+        else if (c->io_weight != CGROUP_WEIGHT_INVALID)
+                return c->io_weight;
+        else
+                return CGROUP_WEIGHT_DEFAULT;
+}
+
+static uint64_t cgroup_context_blkio_weight(CGroupContext *c, ManagerState state) {
+        if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
+            c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID)
+                return c->startup_blockio_weight;
+        else if (c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID)
+                return c->blockio_weight;
+        else
+                return CGROUP_BLKIO_WEIGHT_DEFAULT;
+}
+
+static uint64_t cgroup_weight_blkio_to_io(uint64_t blkio_weight) {
+        return CLAMP(blkio_weight * CGROUP_WEIGHT_DEFAULT / CGROUP_BLKIO_WEIGHT_DEFAULT,
+                     CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX);
+}
+
+static uint64_t cgroup_weight_io_to_blkio(uint64_t io_weight) {
+        return CLAMP(io_weight * CGROUP_BLKIO_WEIGHT_DEFAULT / CGROUP_WEIGHT_DEFAULT,
+                     CGROUP_BLKIO_WEIGHT_MIN, CGROUP_BLKIO_WEIGHT_MAX);
+}
+
+static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_t io_weight) {
+        char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
+        dev_t dev;
+        int r;
+
+        r = lookup_block_device(dev_path, &dev);
+        if (r < 0)
+                return;
+
+        xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), io_weight);
+        r = cg_set_attribute("io", u->cgroup_path, "io.weight", buf);
+        if (r < 0)
+                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                              "Failed to set io.weight: %m");
+}
+
+static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint64_t blkio_weight) {
+        char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
+        dev_t dev;
+        int r;
+
+        r = lookup_block_device(dev_path, &dev);
+        if (r < 0)
+                return;
+
+        xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), blkio_weight);
+        r = cg_set_attribute("blkio", u->cgroup_path, "blkio.weight_device", buf);
+        if (r < 0)
+                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                              "Failed to set blkio.weight_device: %m");
+}
+
+static unsigned cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
+        char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)];
+        char buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4];
+        CGroupIOLimitType type;
+        dev_t dev;
+        unsigned n = 0;
+        int r;
+
+        r = lookup_block_device(dev_path, &dev);
+        if (r < 0)
+                return 0;
+
+        for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) {
+                if (limits[type] != cgroup_io_limit_defaults[type]) {
+                        xsprintf(limit_bufs[type], "%" PRIu64, limits[type]);
+                        n++;
+                } else {
+                        xsprintf(limit_bufs[type], "%s", limits[type] == CGROUP_LIMIT_MAX ? "max" : "0");
+                }
+        }
+
+        xsprintf(buf, "%u:%u rbps=%s wbps=%s riops=%s wiops=%s\n", major(dev), minor(dev),
+                 limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX],
+                 limit_bufs[CGROUP_IO_RIOPS_MAX], limit_bufs[CGROUP_IO_WIOPS_MAX]);
+        r = cg_set_attribute("io", u->cgroup_path, "io.max", buf);
+        if (r < 0)
+                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                              "Failed to set io.max: %m");
+        return n;
+}
+
+static unsigned cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) {
+        char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
+        dev_t dev;
+        unsigned n = 0;
+        int r;
+
+        r = lookup_block_device(dev_path, &dev);
+        if (r < 0)
+                return 0;
+
+        if (rbps != CGROUP_LIMIT_MAX)
+                n++;
+        sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), rbps);
+        r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.read_bps_device", buf);
+        if (r < 0)
+                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                              "Failed to set blkio.throttle.read_bps_device: %m");
+
+        if (wbps != CGROUP_LIMIT_MAX)
+                n++;
+        sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), wbps);
+        r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.write_bps_device", buf);
+        if (r < 0)
+                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                              "Failed to set blkio.throttle.write_bps_device: %m");
+
+        return n;
+}
+
+static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
+        return c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX;
+}
+
+static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) {
+        char buf[DECIMAL_STR_MAX(uint64_t) + 1] = "max";
+        int r;
+
+        if (v != CGROUP_LIMIT_MAX)
+                xsprintf(buf, "%" PRIu64 "\n", v);
+
+        r = cg_set_attribute("memory", u->cgroup_path, file, buf);
+        if (r < 0)
+                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                              "Failed to set %s: %m", file);
+}
+
+static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
+        const char *path;
+        CGroupContext *c;
         bool is_root;
         int r;
 
+        assert(u);
+
+        c = unit_get_cgroup_context(u);
+        path = u->cgroup_path;
+
         assert(c);
         assert(path);
 
@@ -325,14 +574,14 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                         c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT);
                 r = cg_set_attribute("cpu", path, "cpu.shares", buf);
                 if (r < 0)
-                        log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                       "Failed to set cpu.shares on %s: %m", path);
+                        log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                                      "Failed to set cpu.shares: %m");
 
                 sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
                 r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf);
                 if (r < 0)
-                        log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                       "Failed to set cpu.cfs_period_us on %s: %m", path);
+                        log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                                      "Failed to set cpu.cfs_period_us: %m");
 
                 if (c->cpu_quota_per_sec_usec != USEC_INFINITY) {
                         sprintf(buf, USEC_FMT "\n", c->cpu_quota_per_sec_usec * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC);
@@ -340,81 +589,192 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                 } else
                         r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1");
                 if (r < 0)
-                        log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                       "Failed to set cpu.cfs_quota_us on %s: %m", path);
+                        log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                                      "Failed to set cpu.cfs_quota_us: %m");
+        }
+
+        if (mask & CGROUP_MASK_IO) {
+                bool has_io = cgroup_context_has_io_config(c);
+                bool has_blockio = cgroup_context_has_blockio_config(c);
+
+                if (!is_root) {
+                        char buf[8+DECIMAL_STR_MAX(uint64_t)+1];
+                        uint64_t weight;
+
+                        if (has_io)
+                                weight = cgroup_context_io_weight(c, state);
+                        else if (has_blockio) {
+                                uint64_t blkio_weight = cgroup_context_blkio_weight(c, state);
+
+                                weight = cgroup_weight_blkio_to_io(blkio_weight);
+
+                                log_cgroup_compat(u, "Applying [Startup]BlockIOWeight %" PRIu64 " as [Startup]IOWeight %" PRIu64,
+                                                  blkio_weight, weight);
+                        } else
+                                weight = CGROUP_WEIGHT_DEFAULT;
+
+                        xsprintf(buf, "default %" PRIu64 "\n", weight);
+                        r = cg_set_attribute("io", path, "io.weight", buf);
+                        if (r < 0)
+                                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                                              "Failed to set io.weight: %m");
+
+                        if (has_io) {
+                                CGroupIODeviceWeight *w;
+
+                                /* FIXME: no way to reset this list */
+                                LIST_FOREACH(device_weights, w, c->io_device_weights)
+                                        cgroup_apply_io_device_weight(u, w->path, w->weight);
+                        } else if (has_blockio) {
+                                CGroupBlockIODeviceWeight *w;
+
+                                /* FIXME: no way to reset this list */
+                                LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
+                                        weight = cgroup_weight_blkio_to_io(w->weight);
+
+                                        log_cgroup_compat(u, "Applying BlockIODeviceWeight %" PRIu64 " as IODeviceWeight %" PRIu64 " for %s",
+                                                          w->weight, weight, w->path);
+
+                                        cgroup_apply_io_device_weight(u, w->path, weight);
+                                }
+                        }
+                }
+
+                /* Apply limits and free ones without config. */
+                if (has_io) {
+                        CGroupIODeviceLimit *l, *next;
+
+                        LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
+                                if (!cgroup_apply_io_device_limit(u, l->path, l->limits))
+                                        cgroup_context_free_io_device_limit(c, l);
+                        }
+                } else if (has_blockio) {
+                        CGroupBlockIODeviceBandwidth *b, *next;
+
+                        LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths) {
+                                uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
+                                CGroupIOLimitType type;
+
+                                for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
+                                        limits[type] = cgroup_io_limit_defaults[type];
+
+                                limits[CGROUP_IO_RBPS_MAX] = b->rbps;
+                                limits[CGROUP_IO_WBPS_MAX] = b->wbps;
+
+                                log_cgroup_compat(u, "Applying BlockIO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as IO{Read|Write}BandwidthMax for %s",
+                                                  b->rbps, b->wbps, b->path);
+
+                                if (!cgroup_apply_io_device_limit(u, b->path, limits))
+                                        cgroup_context_free_blockio_device_bandwidth(c, b);
+                        }
+                }
         }
 
         if (mask & CGROUP_MASK_BLKIO) {
-                char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1,
-                              DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
-                CGroupBlockIODeviceWeight *w;
-                CGroupBlockIODeviceBandwidth *b;
+                bool has_io = cgroup_context_has_io_config(c);
+                bool has_blockio = cgroup_context_has_blockio_config(c);
 
                 if (!is_root) {
-                        sprintf(buf, "%" PRIu64 "\n",
-                                IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->startup_blockio_weight :
-                                c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT);
+                        char buf[DECIMAL_STR_MAX(uint64_t)+1];
+                        uint64_t weight;
+
+                        if (has_blockio)
+                                weight = cgroup_context_blkio_weight(c, state);
+                        else if (has_io) {
+                                uint64_t io_weight = cgroup_context_io_weight(c, state);
+
+                                weight = cgroup_weight_io_to_blkio(cgroup_context_io_weight(c, state));
+
+                                log_cgroup_compat(u, "Applying [Startup]IOWeight %" PRIu64 " as [Startup]BlockIOWeight %" PRIu64,
+                                                  io_weight, weight);
+                        } else
+                                weight = CGROUP_BLKIO_WEIGHT_DEFAULT;
+
+                        xsprintf(buf, "%" PRIu64 "\n", weight);
                         r = cg_set_attribute("blkio", path, "blkio.weight", buf);
                         if (r < 0)
-                                log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                               "Failed to set blkio.weight on %s: %m", path);
-
-                        /* FIXME: no way to reset this list */
-                        LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
-                                dev_t dev;
-
-                                r = lookup_blkio_device(w->path, &dev);
-                                if (r < 0)
-                                        continue;
-
-                                sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight);
-                                r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
-                                if (r < 0)
-                                        log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                                       "Failed to set blkio.weight_device on %s: %m", path);
+                                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                                              "Failed to set blkio.weight: %m");
+
+                        if (has_blockio) {
+                                CGroupBlockIODeviceWeight *w;
+
+                                /* FIXME: no way to reset this list */
+                                LIST_FOREACH(device_weights, w, c->blockio_device_weights)
+                                        cgroup_apply_blkio_device_weight(u, w->path, w->weight);
+                        } else if (has_io) {
+                                CGroupIODeviceWeight *w;
+
+                                /* FIXME: no way to reset this list */
+                                LIST_FOREACH(device_weights, w, c->io_device_weights) {
+                                        weight = cgroup_weight_io_to_blkio(w->weight);
+
+                                        log_cgroup_compat(u, "Applying IODeviceWeight %" PRIu64 " as BlockIODeviceWeight %" PRIu64 " for %s",
+                                                          w->weight, weight, w->path);
+
+                                        cgroup_apply_blkio_device_weight(u, w->path, weight);
+                                }
                         }
                 }
 
-                /* FIXME: no way to reset this list */
-                LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
-                        const char *a;
-                        dev_t dev;
+                /* Apply limits and free ones without config. */
+                if (has_blockio) {
+                        CGroupBlockIODeviceBandwidth *b, *next;
 
-                        r = lookup_blkio_device(b->path, &dev);
-                        if (r < 0)
-                                continue;
+                        LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths) {
+                                if (!cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps))
+                                        cgroup_context_free_blockio_device_bandwidth(c, b);
+                        }
+                } else if (has_io) {
+                        CGroupIODeviceLimit *l, *next;
 
-                        a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device";
+                        LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
+                                log_cgroup_compat(u, "Applying IO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as BlockIO{Read|Write}BandwidthMax for %s",
+                                                  l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX], l->path);
 
-                        sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
-                        r = cg_set_attribute("blkio", path, a, buf);
-                        if (r < 0)
-                                log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                               "Failed to set %s on %s: %m", a, path);
+                                if (!cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]))
+                                        cgroup_context_free_io_device_limit(c, l);
+                        }
                 }
         }
 
         if ((mask & CGROUP_MASK_MEMORY) && !is_root) {
-                if (c->memory_limit != (uint64_t) -1) {
-                        char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+                if (cg_unified() > 0) {
+                        uint64_t max = c->memory_max;
 
-                        sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
+                        if (cgroup_context_has_unified_memory_config(c))
+                                max = c->memory_max;
+                        else {
+                                max = c->memory_limit;
 
-                        if (cg_unified() <= 0)
-                                r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
-                        else
-                                r = cg_set_attribute("memory", path, "memory.max", buf);
+                                if (max != CGROUP_LIMIT_MAX)
+                                        log_cgroup_compat(u, "Applying MemoryLimit %" PRIu64 " as MemoryMax", max);
+                        }
 
+                        cgroup_apply_unified_memory_limit(u, "memory.low", c->memory_low);
+                        cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high);
+                        cgroup_apply_unified_memory_limit(u, "memory.max", max);
                 } else {
-                        if (cg_unified() <= 0)
-                                r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
+                        char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+                        uint64_t val = c->memory_limit;
+
+                        if (val == CGROUP_LIMIT_MAX) {
+                                val = c->memory_max;
+
+                                if (val != CGROUP_LIMIT_MAX)
+                                        log_cgroup_compat(u, "Applying MemoryMax %" PRIi64 " as MemoryLimit", c->memory_max);
+                        }
+
+                        if (val == CGROUP_LIMIT_MAX)
+                                strncpy(buf, "-1\n", sizeof(buf));
                         else
-                                r = cg_set_attribute("memory", path, "memory.max", "max");
-                }
+                                xsprintf(buf, "%" PRIu64 "\n", val);
 
-                if (r < 0)
-                        log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                       "Failed to set memory.limit_in_bytes/memory.max on %s: %m", path);
+                        r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
+                        if (r < 0)
+                                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                                              "Failed to set memory.limit_in_bytes: %m");
+                }
         }
 
         if ((mask & CGROUP_MASK_DEVICES) && !is_root) {
@@ -429,8 +789,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                 else
                         r = cg_set_attribute("devices", path, "devices.allow", "a");
                 if (r < 0)
-                        log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                       "Failed to reset devices.list on %s: %m", path);
+                        log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                                      "Failed to reset devices.list: %m");
 
                 if (c->device_policy == CGROUP_CLOSED ||
                     (c->device_policy == CGROUP_AUTO && c->device_allow)) {
@@ -441,7 +801,11 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                                 "/dev/random\0" "rwm\0"
                                 "/dev/urandom\0" "rwm\0"
                                 "/dev/tty\0" "rwm\0"
-                                "/dev/pts/ptmx\0" "rw\0"; /* /dev/pts/ptmx may not be duplicated, but accessed */
+                                "/dev/pts/ptmx\0" "rw\0" /* /dev/pts/ptmx may not be duplicated, but accessed */
+                                /* Allow /run/elogind/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */
+                                /* Allow /run/systemd/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */
+                                "/run/systemd/inaccessible/chr\0" "rwm\0"
+                                "/run/systemd/inaccessible/blk\0" "rwm\0";
 
                         const char *x, *y;
 
@@ -476,7 +840,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                         else if (startswith(a->path, "char-"))
                                 whitelist_major(path, a->path + 5, 'c', acc);
                         else
-                                log_debug("Ignoring device %s while writing cgroup attribute.", a->path);
+                                log_unit_debug(u, "Ignoring device %s while writing cgroup attribute.", a->path);
                 }
         }
 
@@ -491,8 +855,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                         r = cg_set_attribute("pids", path, "pids.max", "max");
 
                 if (r < 0)
-                        log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                       "Failed to set pids.max on %s: %m", path);
+                        log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+                                      "Failed to set pids.max: %m");
         }
 }
 
@@ -507,15 +871,12 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
             c->cpu_quota_per_sec_usec != USEC_INFINITY)
                 mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
 
-        if (c->blockio_accounting ||
-            c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
-            c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
-            c->blockio_device_weights ||
-            c->blockio_device_bandwidths)
-                mask |= CGROUP_MASK_BLKIO;
+        if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c))
+                mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
 
         if (c->memory_accounting ||
-            c->memory_limit != (uint64_t) -1)
+            c->memory_limit != CGROUP_LIMIT_MAX ||
+            cgroup_context_has_unified_memory_config(c))
                 mask |= CGROUP_MASK_MEMORY;
 
         if (c->device_allow ||
@@ -766,7 +1127,7 @@ int unit_set_cgroup_path(Unit *u, const char *path) {
 }
 
 int unit_watch_cgroup(Unit *u) {
-        _cleanup_free_ char *populated = NULL;
+        _cleanup_free_ char *events = NULL;
         int r;
 
         assert(u);
@@ -780,7 +1141,7 @@ int unit_watch_cgroup(Unit *u) {
         /* Only applies to the unified hierarchy */
         r = cg_unified();
         if (r < 0)
-                return log_unit_error_errno(u, r, "Failed detect wether the unified hierarchy is used: %m");
+                return log_unit_error_errno(u, r, "Failed detect whether the unified hierarchy is used: %m");
         if (r == 0)
                 return 0;
 
@@ -792,11 +1153,11 @@ int unit_watch_cgroup(Unit *u) {
         if (r < 0)
                 return log_oom();
 
-        r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.populated", &populated);
+        r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.events", &events);
         if (r < 0)
                 return log_oom();
 
-        u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, populated, IN_MODIFY);
+        u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, events, IN_MODIFY);
         if (u->cgroup_inotify_wd < 0) {
 
                 if (errno == ENOENT) /* If the directory is already
@@ -858,6 +1219,7 @@ static int unit_create_cgroup(
         /* Keep track that this is now realized */
         u->cgroup_realized = true;
         u->cgroup_realized_mask = target_mask;
+        u->cgroup_enabled_mask = enable_mask;
 
         if (u->type != UNIT_SLICE && !c->delegate) {
 
@@ -887,10 +1249,10 @@ int unit_attach_pids_to_cgroup(Unit *u) {
         return 0;
 }
 
-static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask) {
+static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask, CGroupMask enable_mask) {
         assert(u);
 
-        return u->cgroup_realized && u->cgroup_realized_mask == target_mask;
+        return u->cgroup_realized && u->cgroup_realized_mask == target_mask && u->cgroup_enabled_mask == enable_mask;
 }
 
 /* Check if necessary controllers and attributes for a unit are in place.
@@ -911,7 +1273,9 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
         }
 
         target_mask = unit_get_target_mask(u);
-        if (unit_has_mask_realized(u, target_mask))
+        enable_mask = unit_get_enable_mask(u);
+
+        if (unit_has_mask_realized(u, target_mask, enable_mask))
                 return 0;
 
         /* First, realize parents */
@@ -922,13 +1286,12 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
         }
 
         /* And then do the real work */
-        enable_mask = unit_get_enable_mask(u);
         r = unit_create_cgroup(u, target_mask, enable_mask);
         if (r < 0)
                 return r;
 
         /* Finally, apply the necessary attributes. */
-        cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, state);
+        cgroup_context_apply(u, target_mask, state);
 
         return 0;
 }
@@ -991,7 +1354,7 @@ static void unit_queue_siblings(Unit *u) {
                         /* If the unit doesn't need any new controllers
                          * and has current ones realized, it doesn't need
                          * any changes. */
-                        if (unit_has_mask_realized(m, unit_get_target_mask(m)))
+                        if (unit_has_mask_realized(m, unit_get_target_mask(m), unit_get_enable_mask(m)))
                                 continue;
 
                         unit_add_to_cgroup_queue(m);
@@ -1059,7 +1422,7 @@ void unit_prune_cgroup(Unit *u) {
 
         r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !is_root_slice);
         if (r < 0) {
-                log_debug_errno(r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
+                log_unit_debug_errno(u, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
                 return;
         }
 
@@ -1070,6 +1433,7 @@ void unit_prune_cgroup(Unit *u) {
 
         u->cgroup_realized = false;
         u->cgroup_realized_mask = 0;
+        u->cgroup_enabled_mask = 0;
 }
 
 int unit_search_main_pid(Unit *u, pid_t *ret) {
@@ -1268,7 +1632,7 @@ int manager_setup_cgroup(Manager *m) {
          * it. This is to support live upgrades from older systemd
          * versions where PID 1 was moved there. Also see
          * cg_get_root_path(). */
-        if (!e && m->running_as == MANAGER_SYSTEM) {
+        if (!e && MANAGER_IS_SYSTEM(m)) {
                 e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
                 if (!e)
                         e = endswith(m->cgroup_root, "/system"); /* even more legacy */
@@ -1304,7 +1668,7 @@ int manager_setup_cgroup(Manager *m) {
                 /* 3. Install agent */
                 if (unified) {
 
-                        /* In the unified hierarchy we can can get
+                        /* In the unified hierarchy we can get
                          * cgroup empty notifications via inotify. */
 
 #if 0 /// elogind does not support the unified hierarchy, yet.
@@ -1319,7 +1683,9 @@ int manager_setup_cgroup(Manager *m) {
                         if (r < 0)
                                 return log_error_errno(r, "Failed to watch control group inotify object: %m");
 
-                        r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_IDLE - 5);
+                        /* Process cgroup empty notifications early, but after service notifications and SIGCHLD. Also
+                         * see handling of cgroup agent notifications, for the classic cgroup hierarchy support. */
+                        r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_NORMAL-5);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to set priority of inotify event source: %m");
 
@@ -1328,7 +1694,7 @@ int manager_setup_cgroup(Manager *m) {
 #else
                         return log_error_errno(EOPNOTSUPP, "Unified cgroup hierarchy not supported: %m");
 #endif // 0
-                } else if (m->running_as == MANAGER_SYSTEM) {
+                } else if (MANAGER_IS_SYSTEM(m)) {
 
                         /* On the legacy hierarchy we only get
                          * notifications via cgroup agents. (Which
@@ -1336,7 +1702,7 @@ int manager_setup_cgroup(Manager *m) {
                          * generate events when control groups with
                          * children run empty. */
 
-                        r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, ELOGIND_CGROUP_AGENT_PATH);
+                        r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
                         if (r < 0)
                                 log_warning_errno(r, "Failed to install release agent, ignoring: %m");
                         else if (r > 0)
@@ -1367,11 +1733,9 @@ int manager_setup_cgroup(Manager *m) {
 
                 /* also, move all other userspace processes remaining
                  * in the root cgroup into that scope. */
-                if (!streq(m->cgroup_root, scope_path)) {
-                        r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, false);
-                        if (r < 0)
-                                log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
-                }
+                r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
+                if (r < 0)
+                        log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
 
                 /* 5. And pin it, so that it cannot be unmounted */
                 safe_close(m->pin_cgroupfs_fd);
@@ -1390,7 +1754,7 @@ int manager_setup_cgroup(Manager *m) {
                 return log_error_errno(r, "Failed to determine supported controllers: %m");
 
         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
-                log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & c));
+                log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & CGROUP_CONTROLLER_TO_MASK(c)));
 
         return 0;
 }
@@ -1480,20 +1844,45 @@ Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
 
         return manager_get_unit_by_pid_cgroup(m, pid);
 }
+#endif // 0
 
+#if 0 /// elogind must substitute this with its own variant
 int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
         Unit *u;
 
         assert(m);
         assert(cgroup);
 
+        log_debug("Got cgroup empty notification for: %s", cgroup);
+
         u = manager_get_unit_by_cgroup(m, cgroup);
         if (!u)
                 return 0;
 
         return unit_notify_cgroup_empty(u);
 }
+#else
+int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
+        Session *s;
+
+        assert(m);
+        assert(cgroup);
+
+        log_debug("Got cgroup empty notification for: %s", cgroup);
+
+        s = hashmap_get(m->sessions, cgroup);
+
+        if (s) {
+                session_finalize(s);
+                session_free(s);
+        } else
+                log_warning("Session not found: %s", cgroup);
+
+        return 0;
+}
+#endif // 0
 
+#if 0 /// UNNEEDED by elogind
 int unit_get_memory_current(Unit *u, uint64_t *ret) {
         _cleanup_free_ char *v = NULL;
         int r;
@@ -1623,6 +2012,10 @@ void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
         if (m == 0)
                 return;
 
+        /* always invalidate compat pairs together */
+        if (m & (CGROUP_MASK_IO | CGROUP_MASK_BLKIO))
+                m |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
+
         if ((u->cgroup_realized_mask & m) == 0)
                 return;
 
@@ -1637,7 +2030,7 @@ void manager_invalidate_startup_units(Manager *m) {
         assert(m);
 
         SET_FOREACH(u, m->startup_units, i)
-                unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_BLKIO);
+                unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO);
 }
 
 static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
index 2a5a223eb677212fadf3fa1b5c553b5d686519a4..c3b87bfc5ce5249b6c49013caf1ebd8fb501fa0f 100644 (file)
 #include <stdbool.h>
 
 //#include "list.h"
-#include "logind.h"
 //#include "time-util.h"
+#include "cgroup-util.h"
 
 #if 0 /// UNNEEDED by elogind
 typedef struct CGroupContext CGroupContext;
 typedef struct CGroupDeviceAllow CGroupDeviceAllow;
+typedef struct CGroupIODeviceWeight CGroupIODeviceWeight;
+typedef struct CGroupIODeviceLimit CGroupIODeviceLimit;
 typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
 typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
 
@@ -55,6 +57,18 @@ struct CGroupDeviceAllow {
         bool m:1;
 };
 
+struct CGroupIODeviceWeight {
+        LIST_FIELDS(CGroupIODeviceWeight, device_weights);
+        char *path;
+        uint64_t weight;
+};
+
+struct CGroupIODeviceLimit {
+        LIST_FIELDS(CGroupIODeviceLimit, device_limits);
+        char *path;
+        uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
+};
+
 struct CGroupBlockIODeviceWeight {
         LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights);
         char *path;
@@ -64,16 +78,28 @@ struct CGroupBlockIODeviceWeight {
 struct CGroupBlockIODeviceBandwidth {
         LIST_FIELDS(CGroupBlockIODeviceBandwidth, device_bandwidths);
         char *path;
-        uint64_t bandwidth;
-        bool read;
+        uint64_t rbps;
+        uint64_t wbps;
 };
 
 struct CGroupContext {
         bool cpu_accounting;
+        bool io_accounting;
         bool blockio_accounting;
         bool memory_accounting;
         bool tasks_accounting;
 
+        /* For unified hierarchy */
+        uint64_t io_weight;
+        uint64_t startup_io_weight;
+        LIST_HEAD(CGroupIODeviceWeight, io_device_weights);
+        LIST_HEAD(CGroupIODeviceLimit, io_device_limits);
+
+        uint64_t memory_low;
+        uint64_t memory_high;
+        uint64_t memory_max;
+
+        /* For legacy hierarchies */
         uint64_t cpu_shares;
         uint64_t startup_cpu_shares;
         usec_t cpu_quota_per_sec_usec;
@@ -88,22 +114,23 @@ struct CGroupContext {
         CGroupDevicePolicy device_policy;
         LIST_HEAD(CGroupDeviceAllow, device_allow);
 
+        /* Common */
         uint64_t tasks_max;
 
         bool delegate;
 };
 
-#include "cgroup-util.h"
 #include "unit.h"
 
 void cgroup_context_init(CGroupContext *c);
 void cgroup_context_done(CGroupContext *c);
 void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix);
-void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state);
 
 CGroupMask cgroup_context_get_mask(CGroupContext *c);
 
 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
+void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w);
+void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l);
 void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w);
 void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
 
@@ -126,8 +153,10 @@ void unit_prune_cgroup(Unit *u);
 int unit_watch_cgroup(Unit *u);
 
 int unit_attach_pids_to_cgroup(Unit *u);
-
+#else
+# include "logind.h"
 #endif // 0
+
 int manager_setup_cgroup(Manager *m);
 void manager_shutdown_cgroup(Manager *m, bool delete);
 
@@ -149,8 +178,10 @@ int unit_reset_cpu_usage(Unit *u);
 bool unit_cgroup_delegate(Unit *u);
 
 int unit_notify_cgroup_empty(Unit *u);
+#endif // 0
 int manager_notify_cgroup_empty(Manager *m, const char *group);
 
+#if 0 /// UNNEEDED by elogind
 void unit_invalidate_cgroup(Unit *u, CGroupMask m);
 
 void manager_invalidate_startup_units(Manager *m);
index 0467fe210f9459c2278fb0e13e8e0b5bfb8c77fc..ca8c63b8a446f83453605d1d31b1bf35a37761c9 100644 (file)
@@ -28,6 +28,7 @@
 #include "cgroup-util.h"
 //#include "dev-setup.h"
 //#include "efivars.h"
+#include "fs-util.h"
 #include "label.h"
 //#include "log.h"
 #include "macro.h"
 #include "path-util.h"
 //#include "set.h"
 //#include "smack-util.h"
-#include "string-util.h"
 //#include "strv.h"
 #include "user-util.h"
 //#include "util.h"
 #include "virt.h"
 
+/// Additional includes needed by elogind
+#include "string-util.h"
+
 typedef enum MountMode {
         MNT_NONE  =        0,
         MNT_FATAL =        1 <<  0,
@@ -96,7 +99,7 @@ static const MountPoint mount_table[] = {
 #endif
         { "tmpfs",       "/run",                      "tmpfs",      "mode=755",                MS_NOSUID|MS_NODEV|MS_STRICTATIME,
           NULL,          MNT_FATAL|MNT_IN_CONTAINER },
-        { "cgroup",      "/sys/fs/cgroup",            "cgroup",     "__DEVEL__sane_behavior",  MS_NOSUID|MS_NOEXEC|MS_NODEV,
+        { "cgroup",      "/sys/fs/cgroup",            "cgroup2",    NULL,                      MS_NOSUID|MS_NOEXEC|MS_NODEV,
           cg_is_unified_wanted, MNT_FATAL|MNT_IN_CONTAINER },
 #endif // 0
         { "tmpfs",       "/sys/fs/cgroup",            "tmpfs",      "mode=755",                MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
@@ -119,8 +122,6 @@ static const MountPoint mount_table[] = {
         { "efivarfs",    "/sys/firmware/efi/efivars", "efivarfs",   NULL,                      MS_NOSUID|MS_NOEXEC|MS_NODEV,
           is_efi_boot,   MNT_NONE                   },
 #endif
-        { "kdbusfs",    "/sys/fs/kdbus",             "kdbusfs",    NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
-          is_kdbus_wanted,       MNT_IN_CONTAINER },
 #endif // 0
 };
 
@@ -392,6 +393,7 @@ int mount_setup(bool loaded_policy) {
                 before_relabel = now(CLOCK_MONOTONIC);
 
                 nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+                nftw("/dev/shm", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
                 nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
 
                 after_relabel = now(CLOCK_MONOTONIC);
@@ -421,10 +423,17 @@ int mount_setup(bool loaded_policy) {
          * really needs to stay for good, otherwise software that
          * copied sd-daemon.c into their sources will misdetect
          * systemd. */
-        mkdir_label("/run/systemd", 0755);
-        mkdir_label("/run/systemd/system", 0755);
-        mkdir_label("/run/systemd/inaccessible", 0000);
 #endif // 0
+        (void) mkdir_label("/run/systemd", 0755);
+        (void) mkdir_label("/run/systemd/system", 0755);
+        (void) mkdir_label("/run/systemd/inaccessible", 0000);
+        /* Set up inaccessible items */
+        (void) mknod("/run/systemd/inaccessible/reg", S_IFREG | 0000, 0);
+        (void) mkdir_label("/run/systemd/inaccessible/dir", 0000);
+        (void) mknod("/run/systemd/inaccessible/chr", S_IFCHR | 0000, makedev(0, 0));
+        (void) mknod("/run/systemd/inaccessible/blk", S_IFBLK | 0000, makedev(0, 0));
+        (void) mkfifo("/run/systemd/inaccessible/fifo", 0000);
+        (void) mknod("/run/systemd/inaccessible/sock", S_IFSOCK | 0000, 0);
 
         return 0;
 }
index 17a92b130c60534b60a17777bc860e7a267e90f9..0b0fd87dd1622a69e739c247c5d1224657ab12fe 100644 (file)
@@ -8,7 +8,7 @@
 prefix=@prefix@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
-includedir=@includedir@
+includedir=@includedir@/elogind
 
 Name: elogind
 Description: elogind Library
index 5e801400b7faeea5e73c2843075e5dfdb7d14c02..97b68623bc05a8a60c02f2771af5d93169f53c96 100644 (file)
@@ -325,7 +325,7 @@ global:
         sd_bus_call_method;
         /* sd_bus_call_method_async; */
         sd_bus_get_property;
-        /* sd_bus_get_property_trivial; */
+        sd_bus_get_property_trivial;
         sd_bus_get_property_string;
         /* sd_bus_get_property_strv; */
         /* sd_bus_set_property; */
@@ -498,3 +498,17 @@ global:
  *         sd_journal_restart_fields;
  * } LIBSYSTEMD_227;
 */
+
+/*
+ * These methods are not needed by elogind.
+ * LIBSYSTEMD_230 {
+ * global:
+ *         sd_journal_open_directory_fd;
+ *         sd_journal_open_files_fd;
+ * } LIBSYSTEMD_229;
+*/
+
+LIBSYSTEMD_231 {
+global:
+        sd_event_get_iteration;
+} LIBSYSTEMD_226;
index 3c19f2b108e4f26ebaaa01dbfa57b40907bc3e92..6457cfe093a183cea5e3fe790182e424b18fc54e 100644 (file)
@@ -25,6 +25,7 @@
 #include "bus-error.h"
 
 BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
+#if 0 /// UNNEEDED by elogind
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT,                 ENOENT),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID,              ESRCH),
         SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS,                  EEXIST),
@@ -38,6 +39,8 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,  EDEADLK),
         SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,   EDEADLK),
         SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED,                  ESHUTDOWN),
+        SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_GENERATED,               EADDRNOTAVAIL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_LINKED,                  ELOOP),
         SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,      EBADR),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION,                 EPERM),
         SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN,                ECANCELED),
@@ -48,6 +51,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID,           ENXIO),
         SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS,               EEXIST),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING,        ENOSYS),
+#endif // 0
 
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION,              ENXIO),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID,           ENXIO),
@@ -61,6 +65,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS,        EINPROGRESS),
         SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,     EOPNOTSUPP),
 
+#if 0 /// UNNEEDED by elogind
         SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED,  EALREADY),
 
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS,              ESRCH),
@@ -68,10 +73,8 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS,              ESRCH),
         SD_BUS_ERROR_MAP(BUS_ERROR_INVALID_REPLY,                EINVAL),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_RR,                   ENOENT),
-        SD_BUS_ERROR_MAP(BUS_ERROR_NO_RESOURCES,                 ENOMEM),
         SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP,                   EDEADLK),
         SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED,                      ECANCELED),
-        SD_BUS_ERROR_MAP(BUS_ERROR_CONNECTION_FAILURE,           ECONNREFUSED),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SERVICE,              EUNATCH),
         SD_BUS_ERROR_MAP(BUS_ERROR_DNSSEC_FAILED,                EHOSTUNREACH),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_TRUST_ANCHOR,              EHOSTUNREACH),
@@ -82,6 +85,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
 
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER,             ENXIO),
         SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS,         EBUSY),
+#endif // 0
 
         SD_BUS_ERROR_MAP_END
 };
index fab8748f46169b6df8f95089b9160d567ecb31aa..aad97ff5ca225d2fe663c07df794862fb16fb2d3 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "bus-error.h"
 
+#if 0 /// only system command elogind knows are needed
 #define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
 #define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
 #define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
 #define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
 #define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
 #define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
+#define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated"
+#define BUS_ERROR_UNIT_LINKED "org.freedesktop.systemd1.UnitLinked"
 #define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
 #define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
 #define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
 #define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
+#endif // 0
 
+#if 0 /// no machined in elogind
 #define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
 #define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
 #define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
@@ -46,6 +51,7 @@
 #define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking"
 #define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping"
 #define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
+#endif // 0
 
 #define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
 #define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
@@ -60,6 +66,7 @@
 #define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
 #define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy"
 
+#if 0 /// more services unsupported by elogind
 #define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
 
 #define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
 #define BUS_ERROR_NO_NAME_SERVERS "org.freedesktop.resolve1.NoNameServers"
 #define BUS_ERROR_INVALID_REPLY "org.freedesktop.resolve1.InvalidReply"
 #define BUS_ERROR_NO_SUCH_RR "org.freedesktop.resolve1.NoSuchRR"
-#define BUS_ERROR_NO_RESOURCES "org.freedesktop.resolve1.NoResources"
 #define BUS_ERROR_CNAME_LOOP "org.freedesktop.resolve1.CNameLoop"
 #define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted"
-#define BUS_ERROR_CONNECTION_FAILURE "org.freedesktop.resolve1.ConnectionFailure"
 #define BUS_ERROR_NO_SUCH_SERVICE "org.freedesktop.resolve1.NoSuchService"
 #define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed"
 #define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor"
@@ -82,5 +87,6 @@
 
 #define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
 #define BUS_ERROR_TRANSFER_IN_PROGRESS "org.freedesktop.import1.TransferInProgress"
+#endif // 0
 
 BUS_ERROR_MAP_ELF_USE(bus_common_errors);
index bd6a96b592b740d674a4c59673e38b7ec75f911a..61c1b03505b81bbae8c3497c883d440104edb29c 100644 (file)
@@ -678,6 +678,7 @@ int bus_get_name_creds_kdbus(
             (mask & (SD_BUS_CREDS_PPID|
                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+                     SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
                      SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
@@ -795,6 +796,7 @@ static int bus_get_name_creds_dbus1(
                     ((mask & SD_BUS_CREDS_AUGMENT) &&
                      (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
                               SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+                              SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
                               SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
                               SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
                               SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
@@ -947,6 +949,7 @@ static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **
             (mask & (SD_BUS_CREDS_PPID|
                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+                     SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
                      SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
@@ -1131,8 +1134,7 @@ static int add_name_change_match(sd_bus *bus,
                 item->name_change.old_id.id = old_owner_id;
                 item->name_change.new_id.id = new_owner_id;
 
-                if (name)
-                        memcpy(item->name_change.name, name, l);
+                memcpy_safe(item->name_change.name, name, l);
 
                 /* If the old name is unset or empty, then
                  * this can match against added names */
index 6fe65479a79a6376ce47631ea4470e65267adf5d..9fdfdf44795ae4cba4ea55348ea0b2a950be6877 100644 (file)
@@ -327,7 +327,6 @@ fail:
         return sd_bus_error_set_errno(error, r);
 }
 
-#if 0 /// UNNEEDED by elogind
 _public_ int sd_bus_get_property_trivial(
                 sd_bus *bus,
                 const char *destination,
@@ -369,7 +368,6 @@ _public_ int sd_bus_get_property_trivial(
 fail:
         return sd_bus_error_set_errno(error, r);
 }
-#endif // 0
 
 _public_ int sd_bus_get_property_string(
                 sd_bus *bus,
index 8f93edb8dae317c30f1cdb9393da6f7273ed0b32..d4b9878b17ab50cd4b1fa7b2d6b539347e671b95 100644 (file)
@@ -83,7 +83,7 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) {
 
         if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) {
                 if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
-                        fputs("   <annotation name=\"org.freedesktop.systemd1.Explicit\" value=\"true\"/>\n", i->f);
+                        fputs("   <annotation name=\"org.freedesktop.login1.Explicit\" value=\"true\"/>\n", i->f);
 
                 if (flags & SD_BUS_VTABLE_PROPERTY_CONST)
                         fputs("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n", i->f);
@@ -96,7 +96,7 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) {
         if (!i->trusted &&
             (type == _SD_BUS_VTABLE_METHOD || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) &&
             !(flags & SD_BUS_VTABLE_UNPRIVILEGED))
-                fputs("   <annotation name=\"org.freedesktop.systemd1.Privileged\" value=\"true\"/>\n", i->f);
+                fputs("   <annotation name=\"org.freedesktop.login1.Privileged\" value=\"true\"/>\n", i->f);
 }
 
 static int introspect_write_arguments(struct introspect *i, const char *signature, const char *direction) {
index 7886e3a38a95232a5db259c0d8734b251ff59956..5db011b710cd9f2de18f92c3166663297038dfae 100644 (file)
@@ -1695,52 +1695,6 @@ int bus_kernel_open_bus_fd(const char *bus, char **path) {
         return fd;
 }
 
-#if 0 /// UNNEEDED by elogind
-int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
-        _cleanup_free_ char *path = NULL;
-        struct kdbus_cmd *make;
-        struct kdbus_item *n;
-        const char *name;
-        int fd;
-
-        fd = bus_kernel_open_bus_fd(bus_name, &path);
-        if (fd < 0)
-                return fd;
-
-        make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd, items)) +
-                             ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1),
-                             8);
-        make->size = ALIGN8(offsetof(struct kdbus_cmd, items));
-        make->flags = KDBUS_MAKE_ACCESS_WORLD;
-
-        n = make->items;
-        sprintf(n->str, UID_FMT "-%s", getuid(), ep_name);
-        n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
-        n->type = KDBUS_ITEM_MAKE_NAME;
-        make->size += ALIGN8(n->size);
-        name = n->str;
-
-        if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
-                safe_close(fd);
-                return -errno;
-        }
-
-        if (ep_path) {
-                char *p;
-
-                p = strjoin(dirname(path), "/", name, NULL);
-                if (!p) {
-                        safe_close(fd);
-                        return -ENOMEM;
-                }
-
-                *ep_path = p;
-        }
-
-        return fd;
-}
-#endif // 0
-
 int bus_kernel_try_close(sd_bus *bus) {
         struct kdbus_cmd byebye = { .size = sizeof(byebye) };
 
index feb4ce805010bf30a578afc1851b22bedf0cad8a..3e6930a0d3de2c4ad989369336002e09e0b2bcfc 100644 (file)
@@ -429,6 +429,9 @@ int bus_match_run(
                         r = bus_match_run(bus, c, m);
                         if (r != 0)
                                 return r;
+
+                        if (bus && bus->match_callbacks_modified)
+                                return 0;
                 }
         }
 
@@ -940,7 +943,7 @@ char *bus_match_to_string(struct bus_match_component *components, unsigned n_com
         char *buffer = NULL;
         size_t size = 0;
         unsigned i;
-               int r;
+        int r;
 
         if (n_components <= 0)
                 return strdup("");
index 03b188d4ea0c81c6347a0dc8d45c1e377955cd62..129c612ecd2df126163b2d0fafd292d24dc7077a 100644 (file)
@@ -181,7 +181,7 @@ static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, b
                 if (!np)
                         goto poison;
         } else {
-                /* Initially, the header is allocated as part of of
+                /* Initially, the header is allocated as part of
                  * the sd_bus_message itself, let's replace it by
                  * dynamic data */
 
@@ -1140,10 +1140,7 @@ _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
         assert_return(!m->sealed, -EPERM);
         assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
 
-        if (b)
-                m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
-        else
-                m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
+        SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
 
         return 0;
 }
@@ -1152,10 +1149,7 @@ _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        if (b)
-                m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
-        else
-                m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
+        SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
 
         return 0;
 }
@@ -1164,10 +1158,7 @@ _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        if (b)
-                m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
-        else
-                m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
+        SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
 
         return 0;
 }
@@ -1208,7 +1199,7 @@ struct bus_body_part *message_append_part(sd_bus_message *m) {
 
         part->memfd = -1;
         m->body_end = part;
-        m->n_body_parts ++;
+        m->n_body_parts++;
 
         return part;
 }
@@ -1653,7 +1644,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
         }
 
         if (type == SD_BUS_TYPE_UNIX_FD)
-                m->n_fds ++;
+                m->n_fds++;
 
         if (c->enclosing != SD_BUS_TYPE_ARRAY)
                 c->index++;
@@ -2399,9 +2390,9 @@ int bus_message_append_ap(
 
                 t = types;
                 if (n_array != (unsigned) -1)
-                        n_array --;
+                        n_array--;
                 else {
-                        types ++;
+                        types++;
                         n_struct--;
                 }
 
@@ -2644,8 +2635,7 @@ _public_ int sd_bus_message_append_array(
         if (r < 0)
                 return r;
 
-        if (size > 0)
-                memcpy(p, ptr, size);
+        memcpy_safe(p, ptr, size);
 
         return 0;
 }
@@ -2889,7 +2879,7 @@ static int bus_message_close_header(sd_bus_message *m) {
 
         /* The actual user data is finished now, we just complete the
            variant and struct now (at least on gvariant). Remember
-           this position, so that during parsing we know where to to
+           this position, so that during parsing we know where to
            put the outer container end. */
         m->user_body_size = m->body_size;
 
@@ -3883,7 +3873,7 @@ static int build_struct_offsets(
                 if (r < 0)
                         return r;
                 if (r == 0 && p[n] != 0) /* except the last item */
-                        n_variable ++;
+                        n_variable++;
                 n_total++;
 
                 p += n;
@@ -4483,9 +4473,9 @@ static int message_read_ap(
 
                 t = types;
                 if (n_array != (unsigned) -1)
-                        n_array --;
+                        n_array--;
                 else {
-                        types ++;
+                        types++;
                         n_struct--;
                 }
 
@@ -5686,8 +5676,8 @@ int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
         assert(str);
 
         r = bus_message_get_arg_skip(m, i, &type, NULL);
-                if (r < 0)
-                        return r;
+        if (r < 0)
+                return r;
 
         if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
                 return -ENXIO;
@@ -5704,8 +5694,8 @@ int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
         assert(strv);
 
         r = bus_message_get_arg_skip(m, i, &type, &contents);
-                if (r < 0)
-                        return r;
+        if (r < 0)
+                return r;
 
         if (type != SD_BUS_TYPE_ARRAY)
                 return -ENXIO;
index 2cb341585d0aeffbc38ddb6e502605dcc25d3272..38fc029b5a78114986345c12031c49a7d3ae4565 100644 (file)
@@ -145,7 +145,7 @@ static int add_enumerated_to_set(
                                 continue;
                         }
 
-                        if (!object_path_is_valid(*k)){
+                        if (!object_path_is_valid(*k)) {
                                 free(*k);
                                 r = -EINVAL;
                                 continue;
@@ -337,7 +337,7 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c,
         if (cap == 0)
                 cap = CAP_SYS_ADMIN;
         else
-                cap --;
+                cap--;
 
         r = sd_bus_query_sender_privilege(m, cap);
         if (r < 0)
index c08ff5f51cceeea02946c64d6dce9aa2aaed7ea0..364360ccaea16ebced20c2b87156899353f34d5d 100644 (file)
@@ -206,7 +206,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
         assert(slot->n_ref > 0);
 
         if (slot->n_ref > 1) {
-                slot->n_ref --;
+                slot->n_ref--;
                 return NULL;
         }
 
index a2fb3912393b78b9a2175398ced956355d46f036..cfd775313905a9faa79c1f5c31dd4571f2dbf939 100644 (file)
@@ -60,7 +60,7 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
                 i->iov_base = NULL;
                 i->iov_len = 0;
 
-                (*idx) ++;
+                (*idx)++;
         }
 }
 
@@ -221,7 +221,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
                 peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
         }
 
-        if (!sd_id128_equal(b->server_id, SD_ID128_NULL) &&
+        if (!sd_id128_is_null(b->server_id) &&
             !sd_id128_equal(b->server_id, peer))
                 return -EPERM;
 
@@ -350,7 +350,7 @@ static int bus_socket_auth_write(sd_bus *b, const char *t) {
         if (!p)
                 return -ENOMEM;
 
-        memcpy(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
+        memcpy_safe(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
         memcpy(p + b->auth_iovec[0].iov_len, t, l);
 
         b->auth_iovec[0].iov_base = p;
@@ -787,7 +787,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
 
         n = m->n_iovec * sizeof(struct iovec);
         iov = alloca(n);
-        memcpy(iov, m->iovec, n);
+        memcpy_safe(iov, m->iovec, n);
 
         j = 0;
         iovec_advance(iov, &j, *idx);
@@ -998,7 +998,7 @@ int bus_socket_read_message(sd_bus *bus) {
                                         return -ENOMEM;
                                 }
 
-                                memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
+                                memcpy_safe(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
                                 bus->fds = f;
                                 bus->n_fds += n;
                         } else
index ea26d502859ae8361227ce6ff06dc3d2f23b2eb5..b2e562358bfd461c5a8831ef3ab5ba46ab8acc92 100644 (file)
@@ -24,7 +24,6 @@
 #include "bus-track.h"
 #include "bus-util.h"
 
-
 struct sd_bus_track {
         unsigned n_ref;
         sd_bus *bus;
@@ -130,7 +129,7 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
         assert(track->n_ref > 0);
 
         if (track->n_ref > 1) {
-                track->n_ref --;
+                track->n_ref--;
                 return NULL;
         }
 
index 83d060cdeab75013e3c8255aa82dcd9373a9ed9e..c35bd5a01189e819d297d95d2610a5f63787fb1d 100644 (file)
@@ -316,10 +316,7 @@ _public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
         assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
-        if (b)
-                bus->creds_mask |= mask;
-        else
-                bus->creds_mask &= ~mask;
+        SET_FLAG(bus->creds_mask, mask, b);
 
         /* The well knowns we need unconditionally, so that matches can work */
         bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
@@ -536,7 +533,7 @@ static void skip_address_key(const char **p) {
         *p += strcspn(*p, ",");
 
         if (**p == ',')
-                (*p) ++;
+                (*p)++;
 }
 
 static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
@@ -701,7 +698,7 @@ static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
                                 goto fail;
                         }
 
-                        (*p) ++;
+                        (*p)++;
 
                         if (ul >= n_argv) {
                                 if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) {
@@ -845,7 +842,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
 
         b->sockaddr.un.sun_family = AF_UNIX;
         strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
-        b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + strlen("/var/run/dbus/system_bus_socket");
+        b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un);
 
         return 0;
 }
@@ -1175,7 +1172,7 @@ _public_ int sd_bus_open(sd_bus **ret) {
                         return sd_bus_open_user(ret);
                 else
 #endif // 0
-                return sd_bus_open_system(ret);
+                        return sd_bus_open_system(ret);
         }
 
         r = sd_bus_new(&b);
@@ -1688,7 +1685,7 @@ static int dispatch_wqueue(sd_bus *bus) {
                          * it got full, then all bets are off
                          * anyway. */
 
-                        bus->wqueue_size --;
+                        bus->wqueue_size--;
                         sd_bus_message_unref(bus->wqueue[0]);
                         memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
                         bus->windex = 0;
@@ -1737,7 +1734,7 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
                         /* Dispatch a queued message */
 
                         *m = bus->rqueue[0];
-                        bus->rqueue_size --;
+                        bus->rqueue_size--;
                         memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
                         return 1;
                 }
@@ -1801,7 +1798,7 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
 
                 r = bus_write_message(bus, m, hint_sync_call, &idx);
                 if (r < 0) {
-                        if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+                        if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
                                 bus_enter_closing(bus);
                                 return -ECONNRESET;
                         }
@@ -1829,7 +1826,7 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
                 if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
                         return -ENOMEM;
 
-                bus->wqueue[bus->wqueue_size ++] = sd_bus_message_ref(m);
+                bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m);
         }
 
 finish:
@@ -2077,8 +2074,8 @@ _public_ int sd_bus_call(
 
                                 } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
                                         r = sd_bus_error_copy(error, &incoming->error);
-                                sd_bus_message_unref(incoming);
-                                return r;
+                                        sd_bus_message_unref(incoming);
+                                        return r;
                                 } else {
                                         r = -EIO;
                                         goto fail;
@@ -2108,7 +2105,7 @@ _public_ int sd_bus_call(
 
                 r = bus_read_message(bus, false, 0);
                 if (r < 0) {
-                        if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+                        if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
                                 bus_enter_closing(bus);
                                 r = -ECONNRESET;
                         }
@@ -2141,7 +2138,7 @@ _public_ int sd_bus_call(
 
                 r = dispatch_wqueue(bus);
                 if (r < 0) {
-                        if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+                        if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
                                 bus_enter_closing(bus);
                                 r = -ECONNRESET;
                         }
@@ -2281,7 +2278,7 @@ static int process_timeout(sd_bus *bus) {
 
         slot = container_of(c, sd_bus_slot, reply_callback);
 
-        bus->iteration_counter ++;
+        bus->iteration_counter++;
 
         bus->current_message = m;
         bus->current_slot = sd_bus_slot_ref(slot);
@@ -2793,7 +2790,7 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
 
         case BUS_OPENING:
                 r = bus_socket_process_opening(bus);
-                if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+                if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
                         bus_enter_closing(bus);
                         r = 1;
                 } else if (r < 0)
@@ -2804,7 +2801,7 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
 
         case BUS_AUTHENTICATING:
                 r = bus_socket_process_authenticating(bus);
-                if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+                if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
                         bus_enter_closing(bus);
                         r = 1;
                 } else if (r < 0)
@@ -2818,7 +2815,7 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
         case BUS_RUNNING:
         case BUS_HELLO:
                 r = process_running(bus, hint_priority, priority, ret);
-                if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+                if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
                         bus_enter_closing(bus);
                         r = 1;
 
@@ -2943,7 +2940,7 @@ _public_ int sd_bus_flush(sd_bus *bus) {
         for (;;) {
                 r = dispatch_wqueue(bus);
                 if (r < 0) {
-                        if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+                        if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
                                 bus_enter_closing(bus);
                                 return -ECONNRESET;
                         }
@@ -3438,7 +3435,7 @@ _public_ int sd_bus_default(sd_bus **ret) {
                 return sd_bus_default_user(ret);
         else
 #endif // 0
-        return sd_bus_default_system(ret);
+                return sd_bus_default_system(ret);
 }
 
 #if 0 /// UNNEEDED by elogind
index 85d7757e16edfbbed6ee58a3b76452fb91d42acb..766d9ef6ed1b0d944d10b67467a2035f5831b9b1 100644 (file)
@@ -103,7 +103,7 @@ _public_ int sd_listen_fds(int unset_environment) {
 finish:
         unsetenv_all(unset_environment);
         return r;
-        }
+}
 
 _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
         _cleanup_strv_free_ char **l = NULL;
@@ -137,8 +137,8 @@ _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
         } else {
                 r = strv_extend_n(&l, "unknown", n_fds);
                 if (r < 0)
-        return r;
-}
+                        return r;
+        }
 
         *names = l;
         l = NULL;
@@ -313,12 +313,12 @@ _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint
                         if (l < sizeof(struct sockaddr_in))
                                 return -EINVAL;
 
-                        return htons(port) == sockaddr.in.sin_port;
+                        return htobe16(port) == sockaddr.in.sin_port;
                 } else {
                         if (l < sizeof(struct sockaddr_in6))
                                 return -EINVAL;
 
-                        return htons(port) == sockaddr.in6.sin6_port;
+                        return htobe16(port) == sockaddr.in6.sin6_port;
                 }
         }
 
@@ -462,14 +462,12 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
         if (sockaddr.un.sun_path[0] == '@')
                 sockaddr.un.sun_path[0] = 0;
 
-        msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
-        if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
-                msghdr.msg_namelen = sizeof(struct sockaddr_un);
+        msghdr.msg_namelen = SOCKADDR_UN_LEN(sockaddr.un);
 
         have_pid = pid != 0 && pid != getpid();
 
         if (n_fds > 0 || have_pid) {
-                /* CMSG_SPACE(0) may return value different then zero, which results in miscalculated controllen. */
+                /* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */
                 msghdr.msg_controllen =
                         (n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
                         (have_pid ? CMSG_SPACE(sizeof(struct ucred)) : 0);
index e32507942a1223928a4abd02fa0d24c963c6510b..cfd5a55457758a7ceadd8ab9d0299af6f7920926 100644 (file)
@@ -109,8 +109,8 @@ struct sd_event_source {
         int64_t priority;
         unsigned pending_index;
         unsigned prepare_index;
-        unsigned pending_iteration;
-        unsigned prepare_iteration;
+        uint64_t pending_iteration;
+        uint64_t prepare_iteration;
 
         LIST_FIELDS(sd_event_source, sources);
 
@@ -215,9 +215,8 @@ struct sd_event {
 
         pid_t original_pid;
 
-        unsigned iteration;
-        dual_timestamp timestamp;
-        usec_t timestamp_boottime;
+        uint64_t iteration;
+        triple_timestamp timestamp;
         int state;
 
         bool exit_requested:1;
@@ -649,7 +648,7 @@ static int event_make_signal_data(
                 if (sigismember(&d->sigset, sig) > 0) {
                         if (ret)
                                 *ret = d;
-                return 0;
+                        return 0;
                 }
         } else {
                 r = hashmap_ensure_allocated(&e->signal_data, &uint64_hash_ops);
@@ -696,7 +695,7 @@ static int event_make_signal_data(
         ev.data.ptr = d;
 
         r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev);
-        if (r < 0) {
+        if (r < 0)  {
                 r = -errno;
                 goto fail;
         }
@@ -733,7 +732,6 @@ static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig
 
                 /* If all the mask is all-zero we can get rid of the structure */
                 hashmap_remove(e->signal_data, &d->priority);
-                assert(!d->current);
                 safe_close(d->fd);
                 free(d);
                 return;
@@ -953,7 +951,7 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t
                 sd_event_ref(e);
 
         LIST_PREPEND(sources, e->sources, s);
-        e->n_sources ++;
+        e->n_sources++;
 
         return s;
 }
@@ -1074,12 +1072,16 @@ _public_ int sd_event_add_time(
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
 
+        if (!clock_supported(clock)) /* Checks whether the kernel supports the clock */
+                return -EOPNOTSUPP;
+
+        type = clock_to_event_source_type(clock); /* checks whether sd-event supports this clock */
+        if (type < 0)
+                return -EOPNOTSUPP;
+
         if (!callback)
                 callback = time_exit_callback;
 
-        type = clock_to_event_source_type(clock);
-        assert_return(type >= 0, -EOPNOTSUPP);
-
         d = event_get_clock_data(e, type);
         assert(d);
 
@@ -1147,8 +1149,7 @@ _public_ int sd_event_add_signal(
         int r;
 
         assert_return(e, -EINVAL);
-        assert_return(sig > 0, -EINVAL);
-        assert_return(sig < _NSIG, -EINVAL);
+        assert_return(SIGNAL_VALID(sig), -EINVAL);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
 
@@ -1181,10 +1182,10 @@ _public_ int sd_event_add_signal(
         e->signal_sources[sig] = s;
 
         r = event_make_signal_data(e, sig, &d);
-                if (r < 0) {
-                        source_free(s);
-                        return r;
-                }
+        if (r < 0) {
+                source_free(s);
+                return r;
+        }
 
         /* Use the signal name as description for the event source by default */
         (void) sd_event_source_set_description(s, signal_to_string(sig));
@@ -1238,14 +1239,14 @@ _public_ int sd_event_add_child(
                 return r;
         }
 
-        e->n_enabled_child_sources ++;
+        e->n_enabled_child_sources++;
 
         r = event_make_signal_data(e, SIGCHLD, NULL);
-                if (r < 0) {
+        if (r < 0) {
                 e->n_enabled_child_sources--;
-                        source_free(s);
-                        return r;
-                }
+                source_free(s);
+                return r;
+        }
 
         e->need_process_child = true;
 
@@ -1582,7 +1583,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
 
                 event_unmask_signal_data(s->event, old, s->signal.sig);
         } else
-        s->priority = priority;
+                s->priority = priority;
 
         if (s->pending)
                 prioq_reshuffle(s->event->pending, s, &s->pending_index);
@@ -1710,11 +1711,11 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
                         s->enabled = m;
 
                         r = event_make_signal_data(s->event, s->signal.sig, NULL);
-                                if (r < 0) {
-                                        s->enabled = SD_EVENT_OFF;
+                        if (r < 0) {
+                                s->enabled = SD_EVENT_OFF;
                                 event_gc_signal_data(s->event, &s->priority, s->signal.sig);
-                                        return r;
-                                }
+                                return r;
+                        }
 
                         break;
 
@@ -1726,12 +1727,12 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
                         s->enabled = m;
 
                         r = event_make_signal_data(s->event, SIGCHLD, NULL);
-                                        if (r < 0) {
-                                                s->enabled = SD_EVENT_OFF;
+                        if (r < 0) {
+                                s->enabled = SD_EVENT_OFF;
                                 s->event->n_enabled_child_sources--;
                                 event_gc_signal_data(s->event, &s->priority, SIGCHLD);
-                                                return r;
-                                        }
+                                return r;
+                        }
 
                         break;
 
@@ -2220,7 +2221,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
                 if (_unlikely_(n != sizeof(si)))
                         return -EIO;
 
-                assert(si.ssi_signo < _NSIG);
+                assert(SIGNAL_VALID(si.ssi_signo));
 
                 read_one = true;
 
@@ -2547,8 +2548,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
                 goto finish;
         }
 
-        dual_timestamp_get(&e->timestamp);
-        e->timestamp_boottime = now(CLOCK_BOOTTIME);
+        triple_timestamp_get(&e->timestamp);
 
         for (i = 0; i < m; i++) {
 
@@ -2560,7 +2560,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
                         switch (*t) {
 
                         case WAKEUP_EVENT_SOURCE:
-                        r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events);
+                                r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events);
                                 break;
 
                         case WAKEUP_CLOCK_DATA: {
@@ -2589,7 +2589,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
         if (r < 0)
                 goto finish;
 
-        r = process_timer(e, e->timestamp_boottime, &e->boottime);
+        r = process_timer(e, e->timestamp.boottime, &e->boottime);
         if (r < 0)
                 goto finish;
 
@@ -2601,7 +2601,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
         if (r < 0)
                 goto finish;
 
-        r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm);
+        r = process_timer(e, e->timestamp.boottime, &e->boottime_alarm);
         if (r < 0)
                 goto finish;
 
@@ -2780,36 +2780,24 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
         assert_return(e, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);
-        assert_return(IN_SET(clock,
-                             CLOCK_REALTIME,
-                             CLOCK_REALTIME_ALARM,
-                             CLOCK_MONOTONIC,
-                             CLOCK_BOOTTIME,
-                             CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP);
-
-        if (!dual_timestamp_is_set(&e->timestamp)) {
+
+        if (!TRIPLE_TIMESTAMP_HAS_CLOCK(clock))
+                return -EOPNOTSUPP;
+
+        /* Generate a clean error in case CLOCK_BOOTTIME is not available. Note that don't use clock_supported() here,
+         * for a reason: there are systems where CLOCK_BOOTTIME is supported, but CLOCK_BOOTTIME_ALARM is not, but for
+         * the purpose of getting the time this doesn't matter. */
+        if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported())
+                return -EOPNOTSUPP;
+
+        if (!triple_timestamp_is_set(&e->timestamp)) {
                 /* Implicitly fall back to now() if we never ran
                  * before and thus have no cached time. */
                 *usec = now(clock);
                 return 1;
         }
 
-        switch (clock) {
-
-        case CLOCK_REALTIME:
-        case CLOCK_REALTIME_ALARM:
-                *usec = e->timestamp.realtime;
-                break;
-
-        case CLOCK_MONOTONIC:
-                *usec = e->timestamp.monotonic;
-                break;
-
-        default:
-                *usec = e->timestamp_boottime;
-                break;
-        }
-
+        *usec = triple_timestamp_by_clock(&e->timestamp, clock);
         return 0;
 }
 #endif // 0
@@ -2915,3 +2903,11 @@ _public_ int sd_event_get_watchdog(sd_event *e) {
         return e->watchdog;
 }
 #endif // 0
+
+_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
+        assert_return(e, -EINVAL);
+        assert_return(!event_pid_changed(e), -ECHILD);
+
+        *ret = e->iteration;
+        return 0;
+}
diff --git a/src/libelogind/sd-id128/id128-util.c b/src/libelogind/sd-id128/id128-util.c
new file mode 100644 (file)
index 0000000..c3f527d
--- /dev/null
@@ -0,0 +1,194 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "fd-util.h"
+#include "hexdecoct.h"
+#include "id128-util.h"
+#include "io-util.h"
+#include "stdio-util.h"
+
+char *id128_to_uuid_string(sd_id128_t id, char s[37]) {
+        unsigned n, k = 0;
+
+        assert(s);
+
+        /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
+
+        for (n = 0; n < 16; n++) {
+
+                if (IN_SET(n, 4, 6, 8, 10))
+                        s[k++] = '-';
+
+                s[k++] = hexchar(id.bytes[n] >> 4);
+                s[k++] = hexchar(id.bytes[n] & 0xF);
+        }
+
+        assert(k == 36);
+
+        s[k] = 0;
+
+        return s;
+}
+
+bool id128_is_valid(const char *s) {
+        size_t i, l;
+
+        assert(s);
+
+        l = strlen(s);
+        if (l == 32) {
+
+                /* Plain formatted 128bit hex string */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if (!(c >= '0' && c <= '9') &&
+                            !(c >= 'a' && c <= 'z') &&
+                            !(c >= 'A' && c <= 'Z'))
+                                return false;
+                }
+
+        } else if (l == 36) {
+
+                /* Formatted UUID */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
+                                if (c != '-')
+                                        return false;
+                        } else {
+                                if (!(c >= '0' && c <= '9') &&
+                                    !(c >= 'a' && c <= 'z') &&
+                                    !(c >= 'A' && c <= 'Z'))
+                                        return false;
+                        }
+                }
+
+        } else
+                return false;
+
+        return true;
+}
+
+int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
+        char buffer[36 + 2];
+        ssize_t l;
+
+        assert(fd >= 0);
+        assert(f < _ID128_FORMAT_MAX);
+
+        /* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both
+         * optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they
+         * aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you
+         * accept". */
+
+        l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */
+        if (l < 0)
+                return (int) l;
+        if (l == 0) /* empty? */
+                return -ENOMEDIUM;
+
+        switch (l) {
+
+        case 33: /* plain UUID with trailing newline */
+                if (buffer[32] != '\n')
+                        return -EINVAL;
+
+                /* fall through */
+        case 32: /* plain UUID without trailing newline */
+                if (f == ID128_UUID)
+                        return -EINVAL;
+
+                buffer[32] = 0;
+                break;
+
+        case 37: /* RFC UUID with trailing newline */
+                if (buffer[36] != '\n')
+                        return -EINVAL;
+
+                /* fall through */
+        case 36: /* RFC UUID without trailing newline */
+                if (f == ID128_PLAIN)
+                        return -EINVAL;
+
+                buffer[36] = 0;
+                break;
+
+        default:
+                return -EINVAL;
+        }
+
+        return sd_id128_from_string(buffer, ret);
+}
+
+int id128_read(const char *p, Id128Format f, sd_id128_t *ret) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0)
+                return -errno;
+
+        return id128_read_fd(fd, f, ret);
+}
+
+int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
+        char buffer[36 + 2];
+        size_t sz;
+        int r;
+
+        assert(fd >= 0);
+        assert(f < _ID128_FORMAT_MAX);
+
+        if (f != ID128_UUID) {
+                sd_id128_to_string(id, buffer);
+                buffer[32] = '\n';
+                sz = 33;
+        } else {
+                id128_to_uuid_string(id, buffer);
+                buffer[36] = '\n';
+                sz = 37;
+        }
+
+        r = loop_write(fd, buffer, sz, false);
+        if (r < 0)
+                return r;
+
+        if (do_sync) {
+                if (fsync(fd) < 0)
+                        return -errno;
+        }
+
+        return r;
+}
+
+int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444);
+        if (fd < 0)
+                return -errno;
+
+        return id128_write_fd(fd, f, id, do_sync);
+}
diff --git a/src/libelogind/sd-id128/id128-util.h b/src/libelogind/sd-id128/id128-util.h
new file mode 100644 (file)
index 0000000..3ba59ac
--- /dev/null
@@ -0,0 +1,45 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+
+#include "sd-id128.h"
+#include "macro.h"
+
+char *id128_to_uuid_string(sd_id128_t id, char s[37]);
+
+/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */
+#define ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
+bool id128_is_valid(const char *s) _pure_;
+
+typedef enum Id128Format {
+        ID128_ANY,
+        ID128_PLAIN,  /* formatted as 32 hex chars as-is */
+        ID128_UUID,   /* formatted as 36 character uuid string */
+        _ID128_FORMAT_MAX,
+} Id128Format;
+
+int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret);
+int id128_read(const char *p, Id128Format f, sd_id128_t *ret);
+
+int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync);
+int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync);
index 81bd84264430844110a4343521404b8f0ee4bc12..9f47d04e61b26f1fe61750ae2858e87d4bf93172 100644 (file)
 
 #include "fd-util.h"
 #include "hexdecoct.h"
+#include "id128-util.h"
 #include "io-util.h"
 #include "macro.h"
- #include "random-util.h"
+#include "random-util.h"
 #include "util.h"
 
 _public_ char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]) {
@@ -51,7 +52,6 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         bool is_guid = false;
 
         assert_return(s, -EINVAL);
-        assert_return(ret, -EINVAL);
 
         for (n = 0, i = 0; n < 16;) {
                 int a, b;
@@ -89,121 +89,57 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         if (s[i] != 0)
                 return -EINVAL;
 
-        *ret = t;
+        if (ret)
+                *ret = t;
         return 0;
 }
 
-static sd_id128_t 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;
-}
-
 _public_ int sd_id128_get_machine(sd_id128_t *ret) {
-        static thread_local sd_id128_t saved_machine_id;
-        static thread_local bool saved_machine_id_valid = false;
-        _cleanup_close_ int fd = -1;
-        char buf[33];
-        unsigned j;
-        sd_id128_t t;
+        static thread_local sd_id128_t saved_machine_id = {};
         int r;
 
         assert_return(ret, -EINVAL);
 
-        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;
-
-        r = loop_read_exact(fd, buf, 33, false);
-        if (r < 0)
-                return r;
-        if (buf[32] !='\n')
-                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;
+        if (sd_id128_is_null(saved_machine_id)) {
+                r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id);
+                if (r < 0)
+                        return r;
 
-                t.bytes[j] = a << 4 | b;
+                if (sd_id128_is_null(saved_machine_id))
+                        return -EINVAL;
         }
 
-        saved_machine_id = t;
-        saved_machine_id_valid = true;
-
-        *ret = t;
+        *ret = saved_machine_id;
         return 0;
 }
 
 _public_ int sd_id128_get_boot(sd_id128_t *ret) {
-        static thread_local sd_id128_t saved_boot_id;
-        static thread_local bool saved_boot_id_valid = false;
-        _cleanup_close_ int fd = -1;
-        char buf[36];
-        unsigned j;
-        sd_id128_t t;
-        char *p;
+        static thread_local sd_id128_t saved_boot_id = {};
         int r;
 
         assert_return(ret, -EINVAL);
 
-        if (saved_boot_id_valid) {
-                *ret = saved_boot_id;
-                return 0;
+        if (sd_id128_is_null(saved_boot_id)) {
+                r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
+                if (r < 0)
+                        return r;
         }
 
-        fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
-        if (fd < 0)
-                return -errno;
-
-        r = loop_read_exact(fd, buf, 36, false);
-        if (r < 0)
-                return r;
-
-        for (j = 0, p = buf; j < 16; j++) {
-                int a, b;
-
-                if (p >= buf + 35)
-                        return -EIO;
-
-                if (*p == '-') {
-                        p++;
-                        if (p >= buf + 35)
-                                return -EIO;
-                }
-
-                a = unhexchar(p[0]);
-                b = unhexchar(p[1]);
-
-                if (a < 0 || b < 0)
-                        return -EIO;
+        *ret = saved_boot_id;
+        return 0;
+}
 
-                t.bytes[j] = a << 4 | b;
+static sd_id128_t make_v4_uuid(sd_id128_t id) {
+        /* Stolen from generate_random_uuid() of drivers/char/random.c
+         * in the kernel sources */
 
-                p += 2;
-        }
+        /* Set UUID version to 4 --- truly random generation */
+        id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
 
-        saved_boot_id = t;
-        saved_boot_id_valid = true;
+        /* Set the UUID variant to DCE */
+        id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
 
-        *ret = t;
-        return 0;
+        return id;
 }
 
 _public_ int sd_id128_randomize(sd_id128_t *ret) {
index a0bd299d8a677aaa7e94cd1467080a6983b7c651..f41e1a855b37dfbb0a18b94b955f19f0d3afab8c 100644 (file)
@@ -148,7 +148,7 @@ _public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
 
         /* The internal APIs return the empty string for the root
          * cgroup, let's return the "/" in the public APIs instead, as
-         * that's easier and less ambigious for people to grok. */
+         * that's easier and less ambiguous for people to grok. */
         if (isempty(c)) {
                 free(c);
                 c = strdup("/");
@@ -378,7 +378,7 @@ static int file_of_seat(const char *seat, char **_p) {
                 if (!filename_is_valid(seat))
                         return -EINVAL;
 
-        p = strappend("/run/systemd/seats/", seat);
+                p = strappend("/run/systemd/seats/", seat);
         } else {
                 _cleanup_free_ char *buf = NULL;
 
@@ -442,10 +442,10 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) {
 
         r = parse_env_file(p, NEWLINE, variable, &s, NULL);
         if (r == -ENOENT || (r >= 0 && isempty(s))) {
-                        if (array)
-                                *array = NULL;
-                        return 0;
-                }
+                if (array)
+                        *array = NULL;
+                return 0;
+        }
         if (r < 0)
                 return r;
 
index 9e24ab9d9b109ddd350df61ad1c8afe3182c72c7..e0a838d3fef011e8b5b7b43aad84c1a34f03d58f 100644 (file)
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "formats-util.h"
-#include "musl_missing.h"
 #include "string-util.h"
 #include "strv.h"
 #include "util.h"
 
+/// Additional includes needed by elogind
+#include "musl_missing.h"
+
 static void test_login(void) {
         _cleanup_close_pair_ int pair[2] = { -1, -1 };
         _cleanup_free_ char *pp = NULL, *qq = NULL;
index bc9ac41a20eabf0af5319c46db227515075c7542..42dc3d01d6df6a6ef114dc42d7c390ccea265f43 100644 (file)
@@ -1,4 +1,5 @@
 /logind-gperf.c
+/logind.conf
 /org.freedesktop.login1.policy
 /71-seat.rules
 /73-seat-late.rules
index 694df2cfc8a8d59cadf04916d0a9658582acd88a..50dcd2e27580eee3df01c4b1747f25333b4c62e5 100644 (file)
@@ -75,4 +75,7 @@ SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess"
 # software-defined radio communication devices
 ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess"
 
+# 3D printers, CNC machines, laser cutters, 3D scanners, etc.
+ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess"
+
 LABEL="uaccess_end"
diff --git a/src/login/eloginctl.c b/src/login/eloginctl.c
new file mode 100644 (file)
index 0000000..dd0a89d
--- /dev/null
@@ -0,0 +1,543 @@
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+
+#include "bus-error.h"
+#include "bus-util.h"
+#include "eloginctl.h"
+#include "logind-action.h"
+#include "parse-util.h"
+#include "process-util.h"
+#include "sd-login.h"
+#include "sd-messages.h"
+#include "spawn-polkit-agent.h"
+#include "string-util.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "user-util.h"
+#include "virt.h"
+
+
+elogind_action arg_action            = _ACTION_INVALID;
+bool           arg_ask_password      = true;
+bool           arg_ignore_inhibitors = false;
+bool           arg_no_wall           = false;
+BusTransport   arg_transport         = BUS_TRANSPORT_LOCAL;
+char**         arg_wall              = NULL;
+usec_t         arg_when              = 0;
+
+static const struct {
+        HandleAction action;
+        const char*  verb;
+} action_table[_ACTION_MAX] = {
+        [ACTION_POWEROFF]     = { HANDLE_POWEROFF,     "poweroff",    },
+        [ACTION_REBOOT]       = { HANDLE_REBOOT,       "reboot",      },
+        [ACTION_SUSPEND]      = { HANDLE_SUSPEND,      "suspend",     },
+        [ACTION_HIBERNATE]    = { HANDLE_HIBERNATE,    "hibernate",   },
+        [ACTION_HYBRID_SLEEP] = { HANDLE_HYBRID_SLEEP, "hybrid-sleep" },
+};
+
+static int elogind_set_wall_message(sd_bus* bus, const char* msg);
+
+static enum elogind_action verb_to_action(const char *verb) {
+        enum elogind_action i;
+
+        for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
+                if (streq_ptr(action_table[i].verb, verb))
+                        return i;
+
+        return _ACTION_INVALID;
+}
+
+static int check_inhibitors(sd_bus* bus, enum elogind_action a) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_strv_free_ char **sessions = NULL;
+        const char *what, *who, *why, *mode;
+        uint32_t uid, pid;
+        unsigned c = 0;
+        char **s;
+        int r;
+
+        if (arg_ignore_inhibitors)
+                return 0;
+
+        if (arg_when > 0)
+                return 0;
+
+        if (geteuid() == 0)
+                return 0;
+
+        if (!on_tty())
+                return 0;
+
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "ListInhibitors",
+                        NULL,
+                        &reply,
+                        NULL);
+        if (r < 0)
+                /* If logind is not around, then there are no inhibitors... */
+                return 0;
+
+        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
+                _cleanup_free_ char *comm = NULL, *user = NULL;
+                _cleanup_strv_free_ char **sv = NULL;
+
+                if (!streq(mode, "block"))
+                        continue;
+
+                sv = strv_split(what, ":");
+                if (!sv)
+                        return log_oom();
+
+                if ((pid_t) pid < 0)
+                        return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
+
+                if (!strv_contains(sv,
+                                   IN_SET(a,
+                                          ACTION_HALT,
+                                          ACTION_POWEROFF,
+                                          ACTION_REBOOT,
+                                          ACTION_KEXEC) ? "shutdown" : "sleep"))
+                        continue;
+
+                get_process_comm(pid, &comm);
+                user = uid_to_name(uid);
+
+                log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
+                            who, (pid_t) pid, strna(comm), strna(user), why);
+
+                c++;
+        }
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        r = sd_bus_message_exit_container(reply);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        /* Check for current sessions */
+        sd_get_sessions(&sessions);
+        STRV_FOREACH(s, sessions) {
+                _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
+
+                if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
+                        continue;
+
+                if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
+                        continue;
+
+                if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
+                        continue;
+
+                sd_session_get_tty(*s, &tty);
+                sd_session_get_seat(*s, &seat);
+                sd_session_get_service(*s, &service);
+                user = uid_to_name(uid);
+
+                log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
+                c++;
+        }
+
+        if (c <= 0)
+                return 0;
+
+        log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'loginctl -i %s'.",
+                  action_table[a].verb);
+
+        return -EPERM;
+}
+
+int elogind_cancel_shutdown(sd_bus *bus) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        int r;
+
+        r = elogind_set_wall_message(bus, NULL);
+
+        if (r < 0) {
+                log_warning_errno(r, "Failed to set wall message, ignoring: %s",
+                                  bus_error_message(&error, r));
+                sd_bus_error_free(&error);
+        }
+
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "CancelScheduledShutdown",
+                        &error,
+                        NULL, NULL);
+        if (r < 0)
+                return log_warning_errno(r, "Failed to talk to elogind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r));
+
+        return 0;
+}
+
+void elogind_cleanup(void) {
+        polkit_agent_close();
+        strv_free(arg_wall);
+}
+
+static void elogind_log_special(enum elogind_action a) {
+#ifdef ENABLE_DEBUG_ELOGIND
+        switch (a) {
+        case ACTION_HALT:
+                log_struct(LOG_INFO,
+                           LOG_MESSAGE("Halt action called."),
+                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
+                           NULL);
+                break;
+        case ACTION_POWEROFF:
+                log_struct(LOG_INFO,
+                           LOG_MESSAGE("Poweroff action called."),
+                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
+                           NULL);
+                break;
+        case ACTION_REBOOT:
+                log_struct(LOG_INFO,
+                           LOG_MESSAGE("Reboot action called."),
+                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
+                           NULL);
+                break;
+        case ACTION_KEXEC:
+                log_struct(LOG_INFO,
+                           LOG_MESSAGE("KExec action called."),
+                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
+                           NULL);
+                break;
+        case ACTION_SUSPEND:
+                log_struct(LOG_INFO,
+                           LOG_MESSAGE("Suspend action called."),
+                           LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START),
+                           NULL);
+                break;
+        case ACTION_HIBERNATE:
+                log_struct(LOG_INFO,
+                           LOG_MESSAGE("Hibernate action called."),
+                           LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START),
+                           NULL);
+                break;
+        case ACTION_HYBRID_SLEEP:
+                log_struct(LOG_INFO,
+                           LOG_MESSAGE("Hybrid-Sleep action called."),
+                           LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START),
+                           NULL);
+                break;
+        case ACTION_CANCEL_SHUTDOWN:
+                log_struct(LOG_INFO,
+                           LOG_MESSAGE("Cancel Shutdown called."),
+                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
+                           NULL);
+                break;
+        default:
+                break;
+        }
+#endif // ENABLE_DEBUG_ELOGIND
+}
+
+static int elogind_reboot(sd_bus *bus, enum elogind_action a) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *method  = NULL;
+        int r;
+        static const char *table[_ACTION_MAX] = {
+                [ACTION_REBOOT]          = "The system is going down for reboot NOW!",
+                [ACTION_POWEROFF]        = "The system is going down for power-off NOW!"
+        };
+
+        if (!bus)
+                return -EIO;
+
+        switch (a) {
+
+        case ACTION_POWEROFF:
+                method = "PowerOff";
+                break;
+
+        case ACTION_REBOOT:
+                method = "Reboot";
+                break;
+
+        case ACTION_SUSPEND:
+                method = "Suspend";
+                break;
+
+        case ACTION_HIBERNATE:
+                method = "Hibernate";
+                break;
+
+        case ACTION_HYBRID_SLEEP:
+                method = "HybridSleep";
+                break;
+
+        default:
+                return -EINVAL;
+        }
+
+        polkit_agent_open_if_enabled();
+
+        if ( IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT) ) {
+                r = elogind_set_wall_message(bus, table[a]);
+
+                if (r < 0) {
+                        log_warning_errno(r, "Failed to set wall message, ignoring: %s",
+                                          bus_error_message(&error, r));
+                        sd_bus_error_free(&error);
+                }
+        }
+
+        /* Now call elogind itself to request the operation */
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        method,
+                        &error,
+                        NULL,
+                        "b", arg_ask_password);
+
+        if (r < 0)
+                log_error("Failed to execute operation: %s", bus_error_message(&error, r));
+
+        return r;
+}
+
+static int elogind_schedule_shutdown(sd_bus *bus, enum elogind_action a) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *method  = NULL;
+        int r;
+
+        if (!bus)
+                return -EIO;
+
+        switch (a) {
+
+        case ACTION_POWEROFF:
+                method = "poweroff";
+                break;
+
+        case ACTION_REBOOT:
+                method = "reboot";
+                break;
+
+        default:
+                return -EINVAL;
+        }
+
+        r = elogind_set_wall_message(bus, NULL);
+
+        if (r < 0) {
+                log_warning_errno(r, "Failed to set wall message, ignoring: %s",
+                                  bus_error_message(&error, r));
+                sd_bus_error_free(&error);
+        }
+
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "ScheduleShutdown",
+                        &error,
+                        NULL,
+                        "st",
+                        method,
+                        arg_when);
+
+        if (r < 0)
+                log_error("Failed to execute operation: %s", bus_error_message(&error, r));
+
+        return r;
+}
+
+static int elogind_set_wall_message(sd_bus* bus, const char* msg) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *m = NULL;
+        int r;
+
+        if (strv_extend(&arg_wall, msg) < 0)
+                return log_oom();
+
+        m = strv_join(arg_wall, " ");
+        if (!m)
+                return log_oom();
+
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "SetWallMessage",
+                        &error,
+                        NULL,
+                        "sb",
+                        m,
+                        !arg_no_wall);
+
+        if (r < 0)
+                return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
+
+        return 0;
+}
+
+static int parse_shutdown_time_spec(const char *t, usec_t *_u) {
+        assert(t);
+        assert(_u);
+
+        if (streq(t, "now"))
+                *_u = 0;
+        else if (!strchr(t, ':')) {
+                uint64_t u;
+
+                if (safe_atou64(t, &u) < 0)
+                        return -EINVAL;
+
+                *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
+        } else {
+                char *e = NULL;
+                long hour, minute;
+                struct tm tm = {};
+                time_t s;
+                usec_t n;
+
+                errno = 0;
+                hour = strtol(t, &e, 10);
+                if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
+                        return -EINVAL;
+
+                minute = strtol(e+1, &e, 10);
+                if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
+                        return -EINVAL;
+
+                n = now(CLOCK_REALTIME);
+                s = (time_t) (n / USEC_PER_SEC);
+
+                assert_se(localtime_r(&s, &tm));
+
+                tm.tm_hour = (int) hour;
+                tm.tm_min = (int) minute;
+                tm.tm_sec = 0;
+
+                assert_se(s = mktime(&tm));
+
+                *_u = (usec_t) s * USEC_PER_SEC;
+
+                while (*_u <= n)
+                        *_u += USEC_PER_DAY;
+        }
+
+        return 0;
+}
+
+void polkit_agent_open_if_enabled(void) {
+
+        /* Open the polkit agent as a child process if necessary */
+
+        if (!arg_ask_password)
+                return;
+
+        if (arg_transport != BUS_TRANSPORT_LOCAL)
+                return;
+
+        polkit_agent_open();
+}
+
+int start_special(int argc, char *argv[], void *userdata) {
+        sd_bus *bus = userdata;
+        enum elogind_action a;
+        int r;
+        char** wall = NULL;
+
+        assert(argv);
+
+        a = verb_to_action(argv[0]);
+
+        elogind_log_special(a);
+
+        /* For poweroff and reboot, some extra checks are performed: */
+        if ( IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT) ) {
+
+                /* No power off actions in chroot environments */
+                if ( running_in_chroot() > 0 ) {
+                        log_info("Running in chroot, ignoring request.");
+                        return 0;
+                }
+
+                /* Check time argument */
+                if ( (argc > 1) && (ACTION_CANCEL_SHUTDOWN != arg_action)) {
+                        r = parse_shutdown_time_spec(argv[1], &arg_when);
+                        if (r < 0) {
+                                log_error("Failed to parse time specification: %s", argv[optind]);
+                                return r;
+                        }
+                }
+
+                /* The optional user wall message must be set */
+                if ( (argc > 1)
+                  && ( (arg_action == ACTION_CANCEL_SHUTDOWN)
+                    || (0 == arg_when) ) )
+                        /* No time argument for shutdown cancel, or no
+                         * time argument given. */
+                        wall = argv + 1;
+                else if (argc > 2)
+                        /* We skip the time argument */
+                        wall = argv + 2;
+
+                if (wall) {
+                        arg_wall = strv_copy(wall);
+                        if (!arg_wall)
+                                return log_oom();
+                }
+        }
+
+        /* Switch to cancel shutdown, if a shutdown action was requested,
+           and the option to cancel it was set: */
+        if ( IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT)
+          && (arg_action == ACTION_CANCEL_SHUTDOWN) )
+                return elogind_cancel_shutdown(bus);
+
+        r = check_inhibitors(bus, a);
+        if (r < 0)
+                return r;
+
+        /* Perform requested action */
+        if (IN_SET(a,
+                   ACTION_POWEROFF,
+                   ACTION_REBOOT,
+                   ACTION_SUSPEND,
+                   ACTION_HIBERNATE,
+                   ACTION_HYBRID_SLEEP)) {
+                if (arg_when > 0)
+                        return elogind_schedule_shutdown(bus, a);
+                else
+                        return elogind_reboot(bus, a);
+        }
+
+        return -EOPNOTSUPP;
+}
+
diff --git a/src/login/eloginctl.h b/src/login/eloginctl.h
new file mode 100644 (file)
index 0000000..b6e9693
--- /dev/null
@@ -0,0 +1,48 @@
+#pragma once
+#ifndef ELOGIND_SRC_LOGIN_ELOGINCTL_H_INCLUDED
+#define ELOGIND_SRC_LOGIN_ELOGINCTL_H_INCLUDED
+
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+
+#include "sd-bus.h"
+
+
+typedef enum elogind_action {
+        _ACTION_INVALID,
+        ACTION_HALT,
+        ACTION_POWEROFF,
+        ACTION_REBOOT,
+        ACTION_KEXEC,
+        ACTION_SUSPEND,
+        ACTION_HIBERNATE,
+        ACTION_HYBRID_SLEEP,
+        ACTION_CANCEL_SHUTDOWN,
+        _ACTION_MAX
+} elogind_action;
+
+
+int  elogind_cancel_shutdown(sd_bus *bus);
+void elogind_cleanup(void);
+void polkit_agent_open_if_enabled(void);
+int  start_special(int argc, char *argv[], void *userdata);
+
+
+#endif // ELOGIND_SRC_LOGIN_ELOGINCTL_H_INCLUDED
diff --git a/src/login/elogind-action.c b/src/login/elogind-action.c
new file mode 100644 (file)
index 0000000..17e1dd2
--- /dev/null
@@ -0,0 +1,69 @@
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+
+#include "elogind-action.h"
+#include "fd-util.h"
+#include "process-util.h"
+#include "sleep.h"
+#include "sleep-config.h"
+
+
+static int run_helper(const char *helper) {
+        int pid = fork();
+        if (pid < 0) {
+                return log_error_errno(errno, "Failed to fork: %m");
+        }
+
+        if (pid == 0) {
+                /* Child */
+
+                close_all_fds(NULL, 0);
+
+                execlp(helper, helper, NULL);
+                log_error_errno(errno, "Failed to execute %s: %m", helper);
+                _exit(EXIT_FAILURE);
+        }
+
+        return wait_for_terminate_and_warn(helper, pid, true);
+}
+
+int shutdown_or_sleep(Manager *m, HandleAction action) {
+
+        assert(m);
+
+        switch (action) {
+        case HANDLE_POWEROFF:
+                return run_helper(HALT);
+        case HANDLE_REBOOT:
+                return run_helper(REBOOT);
+        case HANDLE_HALT:
+                return run_helper(HALT);
+        case HANDLE_KEXEC:
+                return run_helper(KEXEC);
+        case HANDLE_SUSPEND:
+                return do_sleep("suspend", m->suspend_mode, m->suspend_state);
+        case HANDLE_HIBERNATE:
+                return do_sleep("hibernate", m->hibernate_mode, m->hibernate_state);
+        case HANDLE_HYBRID_SLEEP:
+                return do_sleep("hybrid-sleep", m->hybrid_sleep_mode, m->hybrid_sleep_state);
+        default:
+                return -EINVAL;
+        }
+}
diff --git a/src/login/elogind-action.h b/src/login/elogind-action.h
new file mode 100644 (file)
index 0000000..8df7aad
--- /dev/null
@@ -0,0 +1,30 @@
+#pragma once
+#ifndef ELOGIND_SRC_LOGIN_ELOGIND_ACTION_H_INCLUDED
+#define ELOGIND_SRC_LOGIN_ELOGIND_ACTION_H_INCLUDED
+
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "logind.h"
+
+
+int shutdown_or_sleep(Manager *m, HandleAction action);
+
+
+#endif // ELOGIND_SRC_LOGIN_ELOGIND_ACTION_H_INCLUDED
diff --git a/src/login/elogind-dbus.c b/src/login/elogind-dbus.c
new file mode 100644 (file)
index 0000000..a35ca17
--- /dev/null
@@ -0,0 +1,529 @@
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+
+#include "bus-common-errors.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "elogind-dbus.h"
+#include "process-util.h"
+#include "sd-messages.h"
+#include "sleep-config.h"
+#include "string-util.h"
+#include "strv.h"
+#include "update-utmp.h"
+#include "user-util.h"
+
+
+int have_multiple_sessions(
+                Manager *m,
+                uid_t uid) {
+
+        Session *session;
+        Iterator i;
+
+        assert(m);
+
+        /* Check for other users' sessions. Greeter sessions do not
+         * count, and non-login sessions do not count either. */
+        HASHMAP_FOREACH(session, m->sessions, i)
+                if (session->class == SESSION_USER &&
+                    session->user->uid != uid)
+                        return true;
+
+        return false;
+}
+
+static int bus_manager_log_shutdown(
+                Manager *m,
+                InhibitWhat w,
+                HandleAction action) {
+
+         const char *p, *q;
+
+         assert(m);
+
+         if (w != INHIBIT_SHUTDOWN)
+                 return 0;
+
+         switch (action) {
+         case HANDLE_POWEROFF:
+                 p = "MESSAGE=System is powering down.";
+                 q = "SHUTDOWN=power-off";
+                 break;
+         case HANDLE_HALT:
+                 p = "MESSAGE=System is halting.";
+                 q = "SHUTDOWN=halt";
+                 break;
+         case HANDLE_REBOOT:
+                 p = "MESSAGE=System is rebooting.";
+                 q = "SHUTDOWN=reboot";
+                 break;
+         case HANDLE_KEXEC:
+                 p = "MESSAGE=System is rebooting with kexec.";
+                 q = "SHUTDOWN=kexec";
+                 break;
+         default:
+                 p = "MESSAGE=System is shutting down.";
+                 q = NULL;
+         }
+
+        if (isempty(m->wall_message))
+                p = strjoina(p, ".");
+        else
+                p = strjoina(p, " (", m->wall_message, ").");
+
+        return log_struct(LOG_NOTICE,
+                          LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
+                          p,
+                          q,
+                          NULL);
+}
+
+static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
+
+        static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
+                [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
+                [INHIBIT_SLEEP] = "PrepareForSleep"
+        };
+
+        int active = _active;
+
+        assert(m);
+        assert(w >= 0);
+        assert(w < _INHIBIT_WHAT_MAX);
+        assert(signal_name[w]);
+
+        return sd_bus_emit_signal(m->bus,
+                                  "/org/freedesktop/login1",
+                                  "org.freedesktop.login1.Manager",
+                                  signal_name[w],
+                                  "b",
+                                  active);
+}
+
+static int execute_shutdown_or_sleep(
+                Manager *m,
+                InhibitWhat w,
+                HandleAction action,
+                sd_bus_error *error) {
+
+        char** argv_utmp = NULL;
+        int r;
+
+        assert(m);
+        assert(w >= 0);
+        assert(w < _INHIBIT_WHAT_MAX);
+
+        bus_manager_log_shutdown(m, w, action);
+
+        if (IN_SET(action, HANDLE_HALT, HANDLE_POWEROFF, HANDLE_REBOOT)) {
+
+                /* As we have no systemd update-utmp daemon running, we have to
+                 * set the relevant utmp/wtmp entries ourselves.
+                 */
+
+                if (strv_extend(&argv_utmp, "elogind") < 0)
+                        return log_oom();
+
+                if (HANDLE_REBOOT == action) {
+                        if (strv_extend(&argv_utmp, "reboot") < 0)
+                                return log_oom();
+                } else {
+                        if (strv_extend(&argv_utmp, "shutdown") < 0)
+                                return log_oom();
+                }
+
+                 /* This comes from our patched update-utmp/update-utmp.c */
+                update_utmp(2, argv_utmp, m->bus);
+                strv_free(argv_utmp);
+        }
+
+        /* Now perform the requested action */
+        r = shutdown_or_sleep(m, action);
+
+        /* no more pending actions, whether this failed or not */
+        m->pending_action = HANDLE_IGNORE;
+
+        /* As elogind can not rely on a systemd manager to call all
+         * sleeping processes to wake up, we have to tell them all
+         * by ourselves. */
+        if (w == INHIBIT_SLEEP) {
+                send_prepare_for(m, w, false);
+                m->action_what = 0;
+        } else
+                m->action_what = w;
+
+        if (r < 0)
+                return r;
+
+        /* Make sure the lid switch is ignored for a while */
+        manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
+
+        return 0;
+}
+
+int manager_dispatch_delayed(Manager *manager, bool timeout) {
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        Inhibitor *offending = NULL;
+        int r;
+
+        assert(manager);
+
+        if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
+                return 0;
+
+        if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
+                _cleanup_free_ char *comm = NULL, *u = NULL;
+
+                if (!timeout)
+                        return 0;
+
+                (void) get_process_comm(offending->pid, &comm);
+                u = uid_to_name(offending->uid);
+
+                log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
+                           offending->uid, strna(u),
+                           offending->pid, strna(comm));
+        }
+
+        /* Actually do the operation */
+        r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
+        if (r < 0) {
+                log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
+
+                manager->pending_action = HANDLE_IGNORE;
+                manager->action_what    = 0;
+                /* It is not a critical error for elogind if suspending fails */
+        }
+
+        return 1;
+}
+
+static int manager_inhibit_timeout_handler(
+                        sd_event_source *s,
+                        uint64_t usec,
+                        void *userdata) {
+
+        Manager *manager = userdata;
+        int r;
+
+        assert(manager);
+        assert(manager->inhibit_timeout_source == s);
+
+        r = manager_dispatch_delayed(manager, true);
+        return (r < 0) ? r : 0;
+}
+
+static int delay_shutdown_or_sleep(
+                Manager *m,
+                InhibitWhat w,
+                HandleAction action) {
+
+        int r;
+        usec_t timeout_val;
+
+        assert(m);
+        assert(w >= 0);
+        assert(w < _INHIBIT_WHAT_MAX);
+
+        timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
+
+        if (m->inhibit_timeout_source) {
+                r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_source_set_time() failed: %m");
+
+                r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
+        } else {
+                r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
+                                      timeout_val, 0, manager_inhibit_timeout_handler, m);
+                if (r < 0)
+                        return r;
+        }
+
+        m->pending_action = action;
+        m->action_what = w;
+
+        return 0;
+}
+
+int bus_manager_shutdown_or_sleep_now_or_later(
+                Manager *m,
+                HandleAction action,
+                InhibitWhat w,
+                sd_bus_error *error) {
+
+        bool delayed;
+        int r;
+
+        assert(m);
+        assert(w >= 0);
+        assert(w <= _INHIBIT_WHAT_MAX);
+
+        /* Tell everybody to prepare for shutdown/sleep */
+        send_prepare_for(m, w, true);
+
+        delayed =
+                m->inhibit_delay_max > 0 &&
+                manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
+
+        log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
+                          handle_action_to_string(action),
+                          delayed ? "" : "NOT ");
+
+        if (delayed)
+                /* Shutdown is delayed, keep in mind what we
+                 * want to do, and start a timeout */
+                r = delay_shutdown_or_sleep(m, w, action);
+        else
+                /* Shutdown is not delayed, execute it
+                 * immediately */
+                r = execute_shutdown_or_sleep(m, w, action, error);
+
+        return r;
+}
+
+int verify_shutdown_creds(
+                Manager *m,
+                sd_bus_message *message,
+                InhibitWhat w,
+                bool interactive,
+                const char *action,
+                const char *action_multiple_sessions,
+                const char *action_ignore_inhibit,
+                sd_bus_error *error) {
+
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+        bool multiple_sessions, blocked;
+        uid_t uid;
+        int r;
+
+        assert(m);
+        assert(message);
+        assert(w >= 0);
+        assert(w <= _INHIBIT_WHAT_MAX);
+
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_creds_get_euid(creds, &uid);
+        if (r < 0)
+                return r;
+
+        r = have_multiple_sessions(m, uid);
+        if (r < 0)
+                return r;
+
+        multiple_sessions = r > 0;
+        blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
+
+        if (multiple_sessions && action_multiple_sessions) {
+                r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+        }
+
+        if (blocked && action_ignore_inhibit) {
+                r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+        }
+
+        if (!multiple_sessions && !blocked && action) {
+                r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+        }
+
+        return 0;
+}
+
+static int method_do_shutdown_or_sleep(
+                Manager *m,
+                sd_bus_message *message,
+                HandleAction sleep_action,
+                InhibitWhat w,
+                const char *action,
+                const char *action_multiple_sessions,
+                const char *action_ignore_inhibit,
+                const char *sleep_verb,
+                sd_bus_error *error) {
+
+        int interactive, r;
+
+        assert(m);
+        assert(message);
+        assert(w >= 0);
+        assert(w <= _INHIBIT_WHAT_MAX);
+
+        r = sd_bus_message_read(message, "b", &interactive);
+        if (r < 0)
+                return r;
+
+        log_debug_elogind("%s called with action '%s', sleep '%s' (%sinteractive)",
+                          __FUNCTION__, action, sleep_verb,
+                          interactive ? "" : "NOT ");
+
+        /* Don't allow multiple jobs being executed at the same time */
+        if (m->action_what)
+                return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
+
+        if (sleep_verb) {
+                r = can_sleep(m, sleep_verb);
+                if (r < 0)
+                        return r;
+
+                if (r == 0)
+                        return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
+        }
+
+        if (IN_SET(sleep_action, HANDLE_HALT, HANDLE_POWEROFF, HANDLE_REBOOT)) {
+                r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
+                                          action_ignore_inhibit, error);
+                log_debug_elogind("verify_shutdown_creds() returned %d", r);
+                if (r != 0)
+                        return r;
+        }
+
+        r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error);
+        if (r < 0)
+                return r;
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Manager *m = userdata;
+
+        log_debug_elogind("%s called", __FUNCTION__);
+
+        return method_do_shutdown_or_sleep(
+                        m, message,
+                        HANDLE_POWEROFF,
+                        INHIBIT_SHUTDOWN,
+                        "org.freedesktop.login1.power-off",
+                        "org.freedesktop.login1.power-off-multiple-sessions",
+                        "org.freedesktop.login1.power-off-ignore-inhibit",
+                        NULL,
+                        error);
+}
+
+int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Manager *m = userdata;
+
+        log_debug_elogind("%s called", __FUNCTION__);
+
+        return method_do_shutdown_or_sleep(
+                        m, message,
+                        HANDLE_REBOOT,
+                        INHIBIT_SHUTDOWN,
+                        "org.freedesktop.login1.reboot",
+                        "org.freedesktop.login1.reboot-multiple-sessions",
+                        "org.freedesktop.login1.reboot-ignore-inhibit",
+                        NULL,
+                        error);
+}
+
+int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Manager *m = userdata;
+
+        log_debug_elogind("%s called", __FUNCTION__);
+
+        return method_do_shutdown_or_sleep(
+                        m, message,
+                        HANDLE_SUSPEND,
+                        INHIBIT_SLEEP,
+                        "org.freedesktop.login1.suspend",
+                        "org.freedesktop.login1.suspend-multiple-sessions",
+                        "org.freedesktop.login1.suspend-ignore-inhibit",
+                        "suspend",
+                        error);
+}
+
+int manager_scheduled_shutdown_handler(
+                        sd_event_source *s,
+                        uint64_t usec,
+                        void *userdata) {
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        Manager *m = userdata;
+        HandleAction action;
+        int r;
+
+        assert(m);
+
+        if (isempty(m->scheduled_shutdown_type))
+                return 0;
+
+        if (streq(m->scheduled_shutdown_type, "halt"))
+                action = HANDLE_HALT;
+        else if (streq(m->scheduled_shutdown_type, "poweroff"))
+                action = HANDLE_POWEROFF;
+        else
+                action = HANDLE_REBOOT;
+
+        r = execute_shutdown_or_sleep(m, 0, action, &error);
+        if (r < 0)
+                return log_error_errno(r, "Unable to execute transition to %s: %m", m->scheduled_shutdown_type);
+
+        return 0;
+}
+
+int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Manager *m = userdata;
+
+        log_debug_elogind("%s called", __FUNCTION__);
+
+        return method_do_shutdown_or_sleep(
+                        m, message,
+                        HANDLE_HIBERNATE,
+                        INHIBIT_SLEEP,
+                        "org.freedesktop.login1.hibernate",
+                        "org.freedesktop.login1.hibernate-multiple-sessions",
+                        "org.freedesktop.login1.hibernate-ignore-inhibit",
+                        "hibernate",
+                        error);
+}
+
+int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Manager *m = userdata;
+
+        log_debug_elogind("%s called", __FUNCTION__);
+
+        return method_do_shutdown_or_sleep(
+                        m, message,
+                        HANDLE_HYBRID_SLEEP,
+                        INHIBIT_SLEEP,
+                        "org.freedesktop.login1.hibernate",
+                        "org.freedesktop.login1.hibernate-multiple-sessions",
+                        "org.freedesktop.login1.hibernate-ignore-inhibit",
+                        "hybrid-sleep",
+                        error);
+}
diff --git a/src/login/elogind-dbus.h b/src/login/elogind-dbus.h
new file mode 100644 (file)
index 0000000..4b7640d
--- /dev/null
@@ -0,0 +1,41 @@
+#pragma once
+#ifndef ELOGIND_SRC_LOGIN_ELOGIND_DBUS_H_INCLUDED
+#define ELOGIND_SRC_LOGIN_ELOGIND_DBUS_H_INCLUDED
+
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "logind.h"
+
+int have_multiple_sessions(Manager *m, uid_t uid);
+int manager_scheduled_shutdown_handler(sd_event_source *s, uint64_t usec,
+                                       void *userdata);
+int method_hibernate   (sd_bus_message *message, void *userdata, sd_bus_error *error);
+int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int method_poweroff    (sd_bus_message *message, void *userdata, sd_bus_error *error);
+int method_reboot      (sd_bus_message *message, void *userdata, sd_bus_error *error);
+int method_suspend     (sd_bus_message *message, void *userdata, sd_bus_error *error);
+int verify_shutdown_creds(Manager *m, sd_bus_message *message, InhibitWhat w,
+                          bool interactive, const char *action,
+                          const char *action_multiple_sessions,
+                          const char *action_ignore_inhibit,
+                          sd_bus_error *error);
+
+
+#endif // ELOGIND_SRC_LOGIN_ELOGIND_DBUS_H_INCLUDED
index 7933508f2bd33d8d3951209cc66a00dc39571208..f188a8e548fb8926e89ed037137b50c098eb39d8 100644 (file)
@@ -8,4 +8,5 @@ m4_ifdef(`HAVE_SELINUX',
 session  required pam_selinux.so close
 session  required pam_selinux.so nottys open
 )m4_dnl
+session  required pam_loginuid.so
 session  include system-auth
diff --git a/src/login/elogind.c b/src/login/elogind.c
new file mode 100644 (file)
index 0000000..5ff9ed7
--- /dev/null
@@ -0,0 +1,286 @@
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+
+#include "bus-util.h"
+#include "cgroup.h"
+#include "elogind.h"
+#include "fd-util.h"
+#include "mount-setup.h"
+#include "socket-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "umask-util.h"
+
+
+#define CGROUPS_AGENT_RCVBUF_SIZE (8*1024*1024)
+
+
+static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+        Manager *m = userdata;
+        const char *cgroup;
+        uid_t sender_uid;
+        int r;
+
+        assert(message);
+        assert(m);
+
+        /* only accept org.freedesktop.login1.Agent from UID=0 */
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_creds_get_euid(creds, &sender_uid);
+        if (r < 0 || sender_uid != 0)
+                return 0;
+
+        /* parse 'cgroup-empty' notification */
+        r = sd_bus_message_read(message, "s", &cgroup);
+        if (r < 0) {
+                bus_log_parse_error(r);
+                return 0;
+        }
+
+        manager_notify_cgroup_empty(m, cgroup);
+
+        return 0;
+}
+
+/// Add-On for manager_connect_bus()
+/// Original: src/core/dbus.c:bus_setup_system()
+void elogind_bus_setup_system(Manager* m) {
+        int r;
+
+        assert(m);
+        assert(m->bus);
+
+        /* if we are a user instance we get the Released message via the system bus */
+        if (MANAGER_IS_USER(m)) {
+                r = sd_bus_add_match(
+                                m->bus,
+                                NULL,
+                                "type='signal',"
+                                "interface='org.freedesktop.login1.Agent',"
+                                "member='Released',"
+                                "path='/org/freedesktop.login1/agent'",
+                                signal_agent_released, m);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to register Released match on system bus: %m");
+        }
+
+        log_debug("Successfully connected to system bus.");
+}
+
+static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
+        char buf[PATH_MAX+1];
+        ssize_t n;
+
+        n = recv(fd, buf, sizeof(buf), 0);
+        if (n < 0)
+                return log_error_errno(errno, "Failed to read cgroups agent message: %m");
+        if (n == 0) {
+                log_error("Got zero-length cgroups agent message, ignoring.");
+                return 0;
+        }
+        if ((size_t) n >= sizeof(buf)) {
+                log_error("Got overly long cgroups agent message, ignoring.");
+                return 0;
+        }
+
+        if (memchr(buf, 0, n)) {
+                log_error("Got cgroups agent message with embedded NUL byte, ignoring.");
+                return 0;
+        }
+        buf[n] = 0;
+
+        manager_notify_cgroup_empty(m, buf);
+
+        return 0;
+}
+
+/// Add-On for manager_connect_bus()
+/// Original: src/core/manager.c:manager_setup_cgroups_agent()
+int elogind_setup_cgroups_agent(Manager *m) {
+
+        static const union sockaddr_union sa = {
+                .un.sun_family = AF_UNIX,
+                .un.sun_path = "/run/systemd/cgroups-agent",
+        };
+        int r = 0;
+
+        /* This creates a listening socket we receive cgroups agent messages on. We do not use D-Bus for delivering
+         * these messages from the cgroups agent binary to PID 1, as the cgroups agent binary is very short-living, and
+         * each instance of it needs a new D-Bus connection. Since D-Bus connections are SOCK_STREAM/AF_UNIX, on
+         * overloaded systems the backlog of the D-Bus socket becomes relevant, as not more than the configured number
+         * of D-Bus connections may be queued until the kernel will start dropping further incoming connections,
+         * possibly resulting in lost cgroups agent messages. To avoid this, we'll use a private SOCK_DGRAM/AF_UNIX
+         * socket, where no backlog is relevant as communication may take place without an actual connect() cycle, and
+         * we thus won't lose messages.
+         *
+         * Note that PID 1 will forward the agent message to system bus, so that the user systemd instance may listen
+         * to it. The system instance hence listens on this special socket, but the user instances listen on the system
+         * bus for these messages. */
+
+        if (m->test_run)
+                return 0;
+
+        if (!MANAGER_IS_SYSTEM(m))
+                return 0;
+
+        if (cg_unified() > 0) /* We don't need this anymore on the unified hierarchy */
+                return 0;
+
+        if (m->cgroups_agent_fd < 0) {
+                _cleanup_close_ int fd = -1;
+
+                /* First free all secondary fields */
+                m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source);
+
+                fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+                if (fd < 0)
+                        return log_error_errno(errno, "Failed to allocate cgroups agent socket: %m");
+
+                fd_inc_rcvbuf(fd, CGROUPS_AGENT_RCVBUF_SIZE);
+
+                (void) unlink(sa.un.sun_path);
+
+                /* Only allow root to connect to this socket */
+                RUN_WITH_UMASK(0077)
+                        r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
+                if (r < 0)
+                        return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
+
+                m->cgroups_agent_fd = fd;
+                fd = -1;
+        }
+
+        if (!m->cgroups_agent_event_source) {
+                r = sd_event_add_io(m->event, &m->cgroups_agent_event_source, m->cgroups_agent_fd, EPOLLIN, manager_dispatch_cgroups_agent_fd, m);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to allocate cgroups agent event source: %m");
+
+                /* Process cgroups notifications early, but after having processed service notification messages or
+                 * SIGCHLD signals, so that a cgroup running empty is always just the last safety net of notification,
+                 * and we collected the metadata the notification and SIGCHLD stuff offers first. Also see handling of
+                 * cgroup inotify for the unified cgroup stuff. */
+                r = sd_event_source_set_priority(m->cgroups_agent_event_source, SD_EVENT_PRIORITY_NORMAL-5);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to set priority of cgroups agent event source: %m");
+
+                (void) sd_event_source_set_description(m->cgroups_agent_event_source, "manager-cgroups-agent");
+        }
+
+        return 0;
+}
+
+/// Add-On for manager_free()
+void elogind_manager_free(Manager* m) {
+
+        manager_shutdown_cgroup(m, true);
+
+        sd_event_source_unref(m->cgroups_agent_event_source);
+
+        safe_close(m->cgroups_agent_fd);
+
+        strv_free(m->suspend_mode);
+        strv_free(m->suspend_state);
+        strv_free(m->hibernate_mode);
+        strv_free(m->hibernate_state);
+        strv_free(m->hybrid_sleep_mode);
+        strv_free(m->hybrid_sleep_state);
+}
+
+/// Add-On for manager_new()
+int elogind_manager_new(Manager* m) {
+        int r = 0;
+
+        m->cgroups_agent_fd = -1;
+        m->pin_cgroupfs_fd  = -1;
+        m->test_run         = false;
+
+        /* Init sleep modes and states */
+        m->suspend_mode       = NULL;
+        m->suspend_state      = NULL;
+        m->hibernate_mode     = NULL;
+        m->hibernate_state    = NULL;
+        m->hybrid_sleep_mode  = NULL;
+        m->hybrid_sleep_state = NULL;
+
+        /* If elogind should be its own controller, mount its cgroup */
+        if (streq(SYSTEMD_CGROUP_CONTROLLER, "name=elogind")) {
+                m->is_system = true;
+                r = mount_setup(true);
+        } else
+                m->is_system = false;
+
+        /* Make cgroups */
+        if (r > -1)
+                r = manager_setup_cgroup(m);
+
+        return r;
+}
+
+/// Add-On for manager_reset_config()
+void elogind_manager_reset_config(Manager* m) {
+
+#ifdef ENABLE_DEBUG_ELOGIND
+        int dbg_cnt;
+#endif // ENABLE_DEBUG_ELOGIND
+
+        /* Set default Sleep config if not already set by logind.conf */
+        if (!m->suspend_state)
+                m->suspend_state = strv_new("mem", "standby", "freeze", NULL);
+        if (!m->hibernate_mode)
+                m->hibernate_mode = strv_new("platform", "shutdown", NULL);
+        if (!m->hibernate_state)
+                m->hibernate_state = strv_new("disk", NULL);
+        if (!m->hybrid_sleep_mode)
+                m->hybrid_sleep_mode = strv_new("suspend", "platform", "shutdown", NULL);
+        if (!m->hybrid_sleep_state)
+                m->hybrid_sleep_state = strv_new("disk", NULL);
+
+#ifdef ENABLE_DEBUG_ELOGIND
+        dbg_cnt = -1;
+        while (m->suspend_mode && m->suspend_mode[++dbg_cnt])
+                log_debug_elogind("suspend_mode[%d] = %s",
+                                  dbg_cnt, m->suspend_mode[dbg_cnt]);
+        dbg_cnt = -1;
+        while (m->suspend_state[++dbg_cnt])
+                log_debug_elogind("suspend_state[%d] = %s",
+                                  dbg_cnt, m->suspend_state[dbg_cnt]);
+        dbg_cnt = -1;
+        while (m->hibernate_mode[++dbg_cnt])
+                log_debug_elogind("hibernate_mode[%d] = %s",
+                                  dbg_cnt, m->hibernate_mode[dbg_cnt]);
+        dbg_cnt = -1;
+        while (m->hibernate_state[++dbg_cnt])
+                log_debug_elogind("hibernate_state[%d] = %s",
+                                  dbg_cnt, m->hibernate_state[dbg_cnt]);
+        dbg_cnt = -1;
+        while (m->hybrid_sleep_mode[++dbg_cnt])
+                log_debug_elogind("hybrid_sleep_mode[%d] = %s",
+                                  dbg_cnt, m->hybrid_sleep_mode[dbg_cnt]);
+        dbg_cnt = -1;
+        while (m->hybrid_sleep_state[++dbg_cnt])
+                log_debug_elogind("hybrid_sleep_state[%d] = %s",
+                                  dbg_cnt, m->hybrid_sleep_state[dbg_cnt]);
+#endif // ENABLE_DEBUG_ELOGIND
+}
diff --git a/src/login/elogind.h b/src/login/elogind.h
new file mode 100644 (file)
index 0000000..155654b
--- /dev/null
@@ -0,0 +1,43 @@
+#pragma once
+#ifndef ELOGIND_SRC_LOGIN_ELOGIN_H_INCLUDED
+#define ELOGIND_SRC_LOGIN_ELOGIN_H_INCLUDED
+
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+
+#include "logind.h"
+#include "sd-bus.h"
+
+
+/// Add-Ons for manager_connect_bus()
+void elogind_bus_setup_system(Manager* m);
+int  elogind_setup_cgroups_agent(Manager *m);
+
+/// Add-On for manager_free()
+void elogind_manager_free(Manager* m);
+
+/// Add-On for manager_new()
+int elogind_manager_new(Manager* m);
+
+/// Add-On for manager_reset_config()
+void elogind_manager_reset_config(Manager* m);
+
+
+#endif // ELOGIND_SRC_LOGIN_ELOGIN_H_INCLUDED
index 6812ec5d44cca54faba185a01e25d603ffd37f26..2eeaf0b9ef0586fdf46f2d57b89d03b28d5e2d8e 100644 (file)
@@ -37,7 +37,7 @@
 #include "parse-util.h"
 #include "process-util.h"
 #include "signal-util.h"
-#include "spawn-polkit-agent.h"
+//#include "spawn-polkit-agent.h"
 #include "strv.h"
 #include "sysfs-show.h"
 #include "terminal-util.h"
 #include "util.h"
 #include "verbs.h"
 
-/// Additional includes for elogind
-#include "logind-action.h"
-#include "musl_missing.h"
-#include "sd-login.h"
-#include "virt.h"
+/// Additional includes needed by elogind
+#include "eloginctl.h"
 
 static char **arg_property = NULL;
 static bool arg_all = false;
+static bool arg_value = false;
 static bool arg_full = false;
 static bool arg_no_pager = false;
 static bool arg_legend = true;
 static const char *arg_kill_who = NULL;
 static int arg_signal = SIGTERM;
+#if 0 /// UNNEEDED by elogind
 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
 static char *arg_host = NULL;
 static bool arg_ask_password = true;
-static bool arg_ignore_inhibitors = false;
-#if 0
 static unsigned arg_lines = 10;
 static OutputMode arg_output = OUTPUT_SHORT;
+#else
+/// Instead we need this:
+extern BusTransport arg_transport;
+static char *arg_host = NULL;
+extern bool arg_ask_password;
+extern bool arg_no_wall;
+extern usec_t arg_when;
+extern bool arg_ignore_inhibitors;
+extern elogind_action arg_action;
 #endif // 0
-static enum action {
-        _ACTION_INVALID,
-        ACTION_POWEROFF,
-        ACTION_REBOOT,
-        ACTION_SUSPEND,
-        ACTION_HIBERNATE,
-        ACTION_HYBRID_SLEEP,
-        ACTION_CANCEL_SHUTDOWN,
-        _ACTION_MAX
-} arg_action;
-
-
-static void pager_open_if_enabled(void) {
-
-        if (arg_no_pager)
-                return;
-
-        pager_open(false);
-}
 
+#if 0 /// UNNEEDED by elogind
 static void polkit_agent_open_if_enabled(void) {
 
         /* Open the polkit agent as a child process if necessary */
@@ -100,7 +88,6 @@ static void polkit_agent_open_if_enabled(void) {
         polkit_agent_open();
 }
 
-#if 0 /// UNNEEDED by elogind
 static OutputFlags get_output_flags(void) {
 
         return
@@ -123,7 +110,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
         assert(bus);
         assert(argv);
 
-        pager_open_if_enabled();
+        pager_open(arg_no_pager, false);
 
         r = sd_bus_call_method(
                         bus,
@@ -170,7 +157,7 @@ static int list_users(int argc, char *argv[], void *userdata) {
         assert(bus);
         assert(argv);
 
-        pager_open_if_enabled();
+        pager_open(arg_no_pager, false);
 
         r = sd_bus_call_method(
                         bus,
@@ -216,7 +203,7 @@ static int list_seats(int argc, char *argv[], void *userdata) {
         assert(bus);
         assert(argv);
 
-        pager_open_if_enabled();
+        pager_open(arg_no_pager, false);
 
         r = sd_bus_call_method(
                         bus,
@@ -257,18 +244,15 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *path = NULL;
         const char *cgroup;
-        int r;
         unsigned c;
+        int r;
 
         assert(bus);
         assert(unit);
 
-        if (arg_transport != BUS_TRANSPORT_LOCAL)
-                return 0;
-
         path = unit_dbus_path_from_name(unit);
         if (!path)
-                return -ENOMEM;
+                return log_oom();
 
         r = sd_bus_get_property(
                         bus,
@@ -276,27 +260,40 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
                         path,
                         interface,
                         "ControlGroup",
-                        &error, &reply, "s");
+                        &error,
+                        &reply,
+                        "s");
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r));
 
         r = sd_bus_message_read(reply, "s", &cgroup);
         if (r < 0)
-                return r;
+                return bus_log_parse_error(r);
 
         if (isempty(cgroup))
                 return 0;
 
-        if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
-                return 0;
-
         c = columns();
         if (c > 18)
                 c -= 18;
         else
                 c = 0;
 
-        show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t  ", c, false, &leader, leader > 0, get_output_flags());
+        r = unit_show_processes(bus, unit, cgroup, "\t\t  ", c, get_output_flags(), &error);
+        if (r == -EBADR) {
+
+                if (arg_transport == BUS_TRANSPORT_REMOTE)
+                        return 0;
+
+                /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
+
+                if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
+                        return 0;
+
+                show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t  ", c, &leader, leader > 0, get_output_flags());
+        } else if (r < 0)
+                return log_error_errno(r, "Failed to dump process list: %s", bus_error_message(&error, r));
+
         return 0;
 }
 #endif // 0
@@ -310,7 +307,7 @@ typedef struct SessionStatusInfo {
         char *seat;
         char *tty;
         char *display;
-        bool remote;
+        int remote;
         char *remote_host;
         char *remote_user;
         char *service;
@@ -324,6 +321,7 @@ typedef struct SessionStatusInfo {
 
 typedef struct UserStatusInfo {
         uid_t uid;
+        int linger;
         char *name;
         struct dual_timestamp timestamp;
         char *state;
@@ -556,8 +554,9 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
 
         if (i.scope) {
                 printf("\t    Unit: %s\n", i.scope);
-#if 0
+#if 0 /// UNNEEDED by elogind
                 show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
+
                 if (arg_transport == BUS_TRANSPORT_LOCAL) {
 
                         show_journal_by_unit(
@@ -573,7 +572,6 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
                                         true,
                                         NULL);
                 }
-
 #endif // 0
         }
 
@@ -584,6 +582,7 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
 
         static const struct bus_properties_map map[]  = {
                 { "Name",               "s",     NULL,                     offsetof(UserStatusInfo, name)                },
+                { "Linger",             "b",     NULL,                     offsetof(UserStatusInfo, linger)              },
                 { "Slice",              "s",     NULL,                     offsetof(UserStatusInfo, slice)               },
                 { "State",              "s",     NULL,                     offsetof(UserStatusInfo, state)               },
                 { "UID",                "u",     NULL,                     offsetof(UserStatusInfo, uid)                 },
@@ -628,20 +627,21 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
                 char **l;
                 printf("\tSessions:");
 
-                STRV_FOREACH(l, i.sessions) {
-                        if (streq_ptr(*l, i.display))
-                                printf(" *%s", *l);
-                        else
-                                printf(" %s", *l);
-                }
+                STRV_FOREACH(l, i.sessions)
+                        printf(" %s%s",
+                               streq_ptr(*l, i.display) ? "*" : "",
+                               *l);
 
                 printf("\n");
         }
 
+        printf("\t  Linger: %s\n", yes_no(i.linger));
+
         if (i.slice) {
                 printf("\t    Unit: %s\n", i.slice);
-#if 0
+#if 0 /// UNNEEDED by elogind
                 show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
+
                 show_journal_by_unit(
                                 stdout,
                                 i.slice,
@@ -654,7 +654,6 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
                                 SD_JOURNAL_LOCAL_ONLY,
                                 true,
                                 NULL);
-
 #endif // 0
         }
 
@@ -715,6 +714,14 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
         return 0;
 }
 
+#define property(name, fmt, ...)                                        \
+        do {                                                            \
+                if (arg_value)                                          \
+                        printf(fmt "\n", __VA_ARGS__);                  \
+                else                                                    \
+                        printf("%s=" fmt "\n", name, __VA_ARGS__);      \
+        } while(0)
+
 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
         int r;
 
@@ -738,7 +745,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
                                 return bus_log_parse_error(r);
 
                         if (arg_all || !isempty(s))
-                                printf("%s=%s\n", name, s);
+                                property(name, "%s", s);
 
                         return 0;
 
@@ -754,8 +761,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
                                 return -EINVAL;
                         }
 
-                        printf("%s=" UID_FMT "\n", name, uid);
-
+                        property(name, UID_FMT, uid);
                         return 0;
                 }
 
@@ -771,14 +777,16 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        printf("%s=", name);
+                        if (!arg_value)
+                                printf("%s=", name);
 
                         while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
                                 printf("%s%s", space ? " " : "", s);
                                 space = true;
                         }
 
-                        printf("\n");
+                        if (space || !arg_value)
+                                printf("\n");
 
                         if (r < 0)
                                 return bus_log_parse_error(r);
@@ -793,7 +801,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
                 break;
         }
 
-        r = bus_print_property(name, m, arg_all);
+        r = bus_print_property(name, m, arg_value, arg_all);
         if (r < 0)
                 return bus_log_parse_error(r);
 
@@ -886,7 +894,7 @@ static int show_session(int argc, char *argv[], void *userdata) {
 
         properties = !strstr(argv[0], "status");
 
-        pager_open_if_enabled();
+        pager_open(arg_no_pager, false);
 
         if (argc <= 1) {
                 /* If not argument is specified inspect the manager
@@ -942,7 +950,7 @@ static int show_user(int argc, char *argv[], void *userdata) {
 
         properties = !strstr(argv[0], "status");
 
-        pager_open_if_enabled();
+        pager_open(arg_no_pager, false);
 
         if (argc <= 1) {
                 /* If not argument is specified inspect the manager
@@ -1002,7 +1010,7 @@ static int show_seat(int argc, char *argv[], void *userdata) {
 
         properties = !strstr(argv[0], "status");
 
-        pager_open_if_enabled();
+        pager_open(arg_no_pager, false);
 
         if (argc <= 1) {
                 /* If not argument is specified inspect the manager
@@ -1353,254 +1361,6 @@ static int terminate_seat(int argc, char *argv[], void *userdata) {
         return 0;
 }
 
-/* Ask elogind, which might grant access to unprivileged users
- * through PolicyKit */
-static int reboot_with_logind(sd_bus *bus, enum action a) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        const char *method;
-        int r;
-        static const char *table[_ACTION_MAX] = {
-                [ACTION_REBOOT]          = "The system is going down for reboot NOW!",
-                [ACTION_POWEROFF]        = "The system is going down for power-off NOW!",
-                [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
-        };
-
-        if (!bus)
-                return -EIO;
-
-        polkit_agent_open_if_enabled();
-
-        switch (a) {
-
-        case ACTION_POWEROFF:
-                method = "PowerOff";
-                break;
-
-        case ACTION_REBOOT:
-                method = "Reboot";
-                break;
-
-        case ACTION_SUSPEND:
-                method = "Suspend";
-                break;
-
-        case ACTION_HIBERNATE:
-                method = "Hibernate";
-                break;
-
-        case ACTION_HYBRID_SLEEP:
-                method = "HybridSleep";
-                break;
-
-        case ACTION_CANCEL_SHUTDOWN:
-                method = "CancelScheduledShutdown";
-                break;
-
-        default:
-                return -EINVAL;
-        }
-
-        if (table[a]) {
-                r = sd_bus_call_method(
-                               bus,
-                               "org.freedesktop.login1",
-                               "/org/freedesktop/login1",
-                               "org.freedesktop.login1.Manager",
-                               "SetWallMessage",
-                               &error,
-                               NULL,
-                               "sb",
-                               table[a],
-                               true);
-
-                if (r < 0) {
-                        log_warning_errno(r, "Failed to set wall message, ignoring: %s",
-                                          bus_error_message(&error, r));
-                        sd_bus_error_free(&error);
-                }
-        }
-
-
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.login1",
-                        "/org/freedesktop/login1",
-                        "org.freedesktop.login1.Manager",
-                        method,
-                        &error,
-                        NULL,
-                        "b", arg_ask_password);
-        if (r < 0)
-                log_error("Failed to execute operation: %s", bus_error_message(&error, r));
-
-        return r;
-}
-
-static const struct {
-        HandleAction action;
-        const char*  verb;
-} action_table[_ACTION_MAX] = {
-        [ACTION_POWEROFF]     = { HANDLE_POWEROFF,     "poweroff",    },
-        [ACTION_REBOOT]       = { HANDLE_REBOOT,       "reboot",      },
-        [ACTION_SUSPEND]      = { HANDLE_SUSPEND,      "suspend",     },
-        [ACTION_HIBERNATE]    = { HANDLE_HIBERNATE,    "hibernate",   },
-        [ACTION_HYBRID_SLEEP] = { HANDLE_HYBRID_SLEEP, "hybrid-sleep" },
-};
-
-static enum action verb_to_action(const char *verb) {
-        enum action i;
-
-        for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
-                if (streq_ptr(action_table[i].verb, verb))
-                        return i;
-
-        return _ACTION_INVALID;
-}
-
-static int check_inhibitors(sd_bus *bus, enum action a) {
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        _cleanup_strv_free_ char **sessions = NULL;
-        const char *what, *who, *why, *mode;
-        uint32_t uid, pid;
-        unsigned c = 0;
-        char **s;
-        int r;
-
-        if (!bus)
-                return 0;
-
-        if (arg_ignore_inhibitors)
-                return 0;
-
-        if (geteuid() == 0)
-                return 0;
-
-        if (!on_tty())
-                return 0;
-
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.login1",
-                        "/org/freedesktop/login1",
-                        "org.freedesktop.login1.Manager",
-                        "ListInhibitors",
-                        NULL,
-                        &reply,
-                        NULL);
-        if (r < 0)
-                /* If logind is not around, then there are no inhibitors... */
-                return 0;
-
-        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
-                _cleanup_free_ char *comm = NULL, *user = NULL;
-                _cleanup_strv_free_ char **sv = NULL;
-
-                if (!streq(mode, "block"))
-                        continue;
-
-                sv = strv_split(what, ":");
-                if (!sv)
-                        return log_oom();
-
-                if ((pid_t) pid < 0)
-                        return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
-
-                if (!strv_contains(sv,
-                                  a == ACTION_POWEROFF ||
-                                  a == ACTION_REBOOT ? "shutdown" : "sleep"))
-                        continue;
-
-                get_process_comm(pid, &comm);
-                user = uid_to_name(uid);
-
-                log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
-                            who, (pid_t) pid, strna(comm), strna(user), why);
-
-                c++;
-        }
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        r = sd_bus_message_exit_container(reply);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        /* Check for current sessions */
-        sd_get_sessions(&sessions);
-        STRV_FOREACH(s, sessions) {
-                _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
-
-                if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
-                        continue;
-
-                if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
-                        continue;
-
-                if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
-                        continue;
-
-                sd_session_get_tty(*s, &tty);
-                sd_session_get_seat(*s, &seat);
-                sd_session_get_service(*s, &service);
-                user = uid_to_name(uid);
-
-                log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
-                c++;
-        }
-
-        if (c <= 0)
-                return 0;
-
-        log_error("Please retry operation after closing inhibitors and logging out other users.\n"
-                  "Alternatively, ignore inhibitors and users with 'loginctl %s -i'.",
-                  action_table[a].verb);
-
-        return -EPERM;
-}
-
-static int start_special(int argc, char *argv[], void *userdata) {
-        sd_bus *bus = userdata;
-        enum action a;
-        int r;
-
-        assert(argv);
-
-        a = verb_to_action(argv[0]);
-
-        r = check_inhibitors(bus, a);
-        if (r < 0)
-                return r;
-
-        /* Now power off actions in chroot environments */
-        if ((a == ACTION_POWEROFF ||
-             a == ACTION_REBOOT) &&
-            (running_in_chroot() > 0) ) {
-                log_info("Running in chroot, ignoring request.");
-                return 0;
-        }
-
-        /* Switch to cancel shutdown, if a shutdown action was requested,
-           and the option to cancel it was set: */
-        if ((a == ACTION_POWEROFF ||
-             a == ACTION_REBOOT) &&
-            (arg_action == ACTION_CANCEL_SHUTDOWN))
-                return reboot_with_logind(bus, arg_action);
-
-        /* Otherwise perform requested action */
-        if (a == ACTION_POWEROFF ||
-            a == ACTION_REBOOT ||
-            a == ACTION_SUSPEND ||
-            a == ACTION_HIBERNATE ||
-            a == ACTION_HYBRID_SLEEP)
-                return reboot_with_logind(bus, a);
-
-        return -EOPNOTSUPP;
-}
-
 static int help(int argc, char *argv[], void *userdata) {
 
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
@@ -1608,22 +1368,28 @@ static int help(int argc, char *argv[], void *userdata) {
                "  -h --help                Show this help\n"
                "     --version             Show package version\n"
                "     --no-pager            Do not pipe output into a pager\n"
+#if 1 /// elogind supports --no-wall
+               "     --no-wall             Do not print any wall message\n"
+#endif // 1
                "     --no-legend           Do not show the headers and footers\n"
                "     --no-ask-password     Don't prompt for password\n"
                "  -H --host=[USER@]HOST    Operate on remote host\n"
                "  -M --machine=CONTAINER   Operate on local container\n"
                "  -p --property=NAME       Show only properties by this name\n"
                "  -a --all                 Show all properties, including empty ones\n"
+               "     --value               When showing properties, only print the value\n"
                "  -l --full                Do not ellipsize output\n"
                "     --kill-who=WHO        Who to send signal to\n"
                "  -s --signal=SIGNAL       Which signal to send\n"
-#if 0
+#if 0 /// UNNEEDED by elogind
                "  -n --lines=INTEGER       Number of journal entries to show\n"
                "  -o --output=STRING       Change journal output mode (short, short-monotonic,\n"
                "                           verbose, export, json, json-pretty, json-sse, cat)\n\n"
+#else
+                /// elogind can cancel shutdowns and allows to ignore inhibitors
+               "  -c                       Cancel a pending shutdown or reboot\n"
+               "  -i --ignore-inhibitors   When shutting down or sleeping, ignore inhibitors\n\n"
 #endif // 0
-               "  -c                       Cancel a pending shutdown\n"
-               "  -i --ignore-inhibitors   When shutting down or sleeping, ignore inhibitors\n"
                "Session Commands:\n"
                "  list-sessions            List sessions\n"
                "  session-status [ID...]   Show session status\n"
@@ -1649,13 +1415,15 @@ static int help(int argc, char *argv[], void *userdata) {
                "  show-seat [NAME...]      Show properties of seats or the manager\n"
                "  attach NAME DEVICE...    Attach one or more devices to a seat\n"
                "  flush-devices            Flush all device associations\n"
-               "  terminate-seat NAME...   Terminate all sessions on one or more seats\n"
+               "  terminate-seat NAME...   Terminate all sessions on one or more seats\n\n"
+#if 1 /// elogind adds some system commands to loginctl
                "System Commands:\n"
-               "  poweroff                 Turn off the machine\n"
-               "  reboot                   Reboot the machine\n"
-               "  suspend                  Suspend the machine to memory\n"
-               "  hibernate                Suspend the machine to disk\n"
-               "  hybrid-sleep             Suspend the machine to memory and disk\n"
+               "  poweroff [TIME] [WALL...] Turn off the machine\n"
+               "  reboot   [TIME] [WALL...] Reboot the machine\n"
+               "  suspend                   Suspend the machine to memory\n"
+               "  hibernate                 Suspend the machine to disk\n"
+               "  hybrid-sleep              Suspend the machine to memory and disk\n"
+#endif // 1
                , program_invocation_short_name);
 
         return 0;
@@ -1665,7 +1433,11 @@ static int parse_argv(int argc, char *argv[]) {
 
         enum {
                 ARG_VERSION = 0x100,
+                ARG_VALUE,
                 ARG_NO_PAGER,
+#if 1 /// elogind supports --no-wall
+                ARG_NO_WALL,
+#endif // 1
                 ARG_NO_LEGEND,
                 ARG_KILL_WHO,
                 ARG_NO_ASK_PASSWORD,
@@ -1676,19 +1448,25 @@ static int parse_argv(int argc, char *argv[]) {
                 { "version",         no_argument,       NULL, ARG_VERSION         },
                 { "property",        required_argument, NULL, 'p'                 },
                 { "all",             no_argument,       NULL, 'a'                 },
+                { "value",           no_argument,       NULL, ARG_VALUE           },
                 { "full",            no_argument,       NULL, 'l'                 },
                 { "no-pager",        no_argument,       NULL, ARG_NO_PAGER        },
+#if 1 /// elogind supports --no-wall
+                { "no-wall",         no_argument,       NULL, ARG_NO_WALL         },
+#endif // 1
                 { "no-legend",       no_argument,       NULL, ARG_NO_LEGEND       },
                 { "kill-who",        required_argument, NULL, ARG_KILL_WHO        },
                 { "signal",          required_argument, NULL, 's'                 },
                 { "host",            required_argument, NULL, 'H'                 },
                 { "machine",         required_argument, NULL, 'M'                 },
                 { "no-ask-password", no_argument,       NULL, ARG_NO_ASK_PASSWORD },
-#if 0
+#if 0 /// UNNEEDED by elogind
                 { "lines",           required_argument, NULL, 'n'                 },
                 { "output",          required_argument, NULL, 'o'                 },
-#endif // 0
+#else
+                /// elogind allows to ignore inhibitors for system commands.
                 { "ignore-inhibitors", no_argument,     NULL, 'i'                 },
+#endif // 0
                 {}
         };
 
@@ -1697,7 +1475,11 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
+#if 0 /// elogind adds some system commands to loginctl
+        while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0)
+#else
         while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:ci", options, NULL)) >= 0)
+#endif // 0
 
                 switch (c) {
 
@@ -1724,10 +1506,15 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_all = true;
                         break;
 
+                case ARG_VALUE:
+                        arg_value = true;
+                        break;
+
                 case 'l':
                         arg_full = true;
                         break;
-#if 0
+
+#if 0 /// UNNEEDED by elogind
                 case 'n':
                         if (safe_atou(optarg, &arg_lines) < 0) {
                                 log_error("Failed to parse lines '%s'", optarg);
@@ -1743,9 +1530,15 @@ static int parse_argv(int argc, char *argv[]) {
                         }
                         break;
 #endif // 0
+
                 case ARG_NO_PAGER:
                         arg_no_pager = true;
                         break;
+#if 1 /// elogind supports --no-wall
+                case ARG_NO_WALL:
+                        arg_no_wall = true;
+                        break;
+#endif // 1
 
                 case ARG_NO_LEGEND:
                         arg_legend = false;
@@ -1776,7 +1569,7 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
-
+#if 1 /// elogind can cancel shutdowns and allows to ignore inhibitors
                 case 'c':
                         arg_action = ACTION_CANCEL_SHUTDOWN;
                         break;
@@ -1784,7 +1577,7 @@ static int parse_argv(int argc, char *argv[]) {
                 case 'i':
                         arg_ignore_inhibitors = true;
                         break;
-
+#endif // 1
                 case '?':
                         return -EINVAL;
 
@@ -1822,20 +1615,26 @@ static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
                 { "attach",            3,        VERB_ANY, 0,            attach            },
                 { "flush-devices",     VERB_ANY, 1,        0,            flush_devices     },
                 { "terminate-seat",    2,        VERB_ANY, 0,            terminate_seat    },
-                { "poweroff",          VERB_ANY, 1,        0,            start_special     },
-                { "reboot",            VERB_ANY, 1,        0,            start_special     },
+#if 1 /// elogind adds some system commands to loginctl
+                { "poweroff",          VERB_ANY, VERB_ANY, 0,            start_special     },
+                { "reboot",            VERB_ANY, VERB_ANY, 0,            start_special     },
                 { "suspend",           VERB_ANY, 1,        0,            start_special     },
                 { "hibernate",         VERB_ANY, 1,        0,            start_special     },
                 { "hybrid-sleep",      VERB_ANY, 1,        0,            start_special     },
                 { "cancel-shutdown",   VERB_ANY, 1,        0,            start_special     },
+#endif // 1
                 {}
         };
 
+#if 1 /// elogind can do shutdown and allows its cancellation
+        if ((argc == optind) && (ACTION_CANCEL_SHUTDOWN == arg_action))
+                return elogind_cancel_shutdown(bus);
+#endif // 1
         return dispatch_verb(argc, argv, verbs, bus);
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
@@ -1858,10 +1657,17 @@ int main(int argc, char *argv[]) {
         r = loginctl_main(argc, argv, bus);
 
 finish:
+        sd_bus_flush_close_unref(bus);
+
         pager_close();
+#if 0 /// elogind does that in elogind_cleanup()
         polkit_agent_close();
+#endif // 0
 
         strv_free(arg_property);
 
+#if 1 /// elogind has some own cleanups to do
+        elogind_cleanup();
+#endif // 1
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
index 4070405190724bb8030d97c8651420c440cce4b3..bcf7b86a3b1d205bd259072345a077cab9464dce 100644 (file)
 #include "formats-util.h"
 #include "logind-action.h"
 #include "process-util.h"
-//#include "sleep-config.h"
+#include "sleep-config.h"
 //#include "special.h"
 #include "string-table.h"
 #include "terminal-util.h"
 #include "user-util.h"
 
-// Additional includes needed by elogind
+/// Additional includes needed by elogind
 #include "fd-util.h"
 #include "fileio.h"
 #include "sd-messages.h"
 #include "strv.h"
 
-
 int manager_handle_action(
                 Manager *m,
                 InhibitWhat inhibit_key,
@@ -112,12 +111,21 @@ int manager_handle_action(
                 return 1;
         }
 
+#if 0 /// elogind needs its own can_sleep() variant.
+        if (handle == HANDLE_SUSPEND)
+                supported = can_sleep("suspend") > 0;
+        else if (handle == HANDLE_HIBERNATE)
+                supported = can_sleep("hibernate") > 0;
+        else if (handle == HANDLE_HYBRID_SLEEP)
+                supported = can_sleep("hybrid-sleep") > 0;
+#else
         if (handle == HANDLE_SUSPEND)
                 supported = can_sleep(m, "suspend") > 0;
         else if (handle == HANDLE_HIBERNATE)
                 supported = can_sleep(m, "hibernate") > 0;
         else if (handle == HANDLE_HYBRID_SLEEP)
                 supported = can_sleep(m, "hybrid-sleep") > 0;
+#endif // 0
         else if (handle == HANDLE_KEXEC)
                 supported = access(KEXEC, X_OK) >= 0;
         else
@@ -133,7 +141,7 @@ int manager_handle_action(
                 return -EALREADY;
         }
 
-        inhibit_operation = handle == HANDLE_SUSPEND || handle == HANDLE_HIBERNATE || handle == HANDLE_HYBRID_SLEEP ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
+        inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
 
         /* If the actual operation is inhibited, warn and fail */
         if (!ignore_inhibited &&
@@ -175,49 +183,6 @@ int manager_handle_action(
         return 1;
 }
 
-static int run_helper(const char *helper) {
-        int pid = fork();
-        if (pid < 0) {
-                return log_error_errno(errno, "Failed to fork: %m");
-        }
-
-        if (pid == 0) {
-                /* Child */
-
-                close_all_fds(NULL, 0);
-
-                execlp(helper, helper, NULL);
-                log_error_errno(errno, "Failed to execute %s: %m", helper);
-                _exit(EXIT_FAILURE);
-        }
-
-        return wait_for_terminate_and_warn(helper, pid, true);
-}
-
-int shutdown_or_sleep(Manager *m, HandleAction action) {
-
-        assert(m);
-
-        switch (action) {
-        case HANDLE_POWEROFF:
-                return run_helper(HALT);
-        case HANDLE_REBOOT:
-                return run_helper(REBOOT);
-        case HANDLE_HALT:
-                return run_helper(HALT);
-        case HANDLE_KEXEC:
-                return run_helper(KEXEC);
-        case HANDLE_SUSPEND:
-                return do_sleep("suspend", m->suspend_mode, m->suspend_state);
-        case HANDLE_HIBERNATE:
-                return do_sleep("hibernate", m->hibernate_mode, m->hibernate_state);
-        case HANDLE_HYBRID_SLEEP:
-                return do_sleep("hybrid-sleep", m->hybrid_sleep_mode, m->hybrid_sleep_state);
-        default:
-                return -EINVAL;
-        }
-}
-
 static const char* const handle_action_table[_HANDLE_ACTION_MAX] = {
         [HANDLE_IGNORE] = "ignore",
         [HANDLE_POWEROFF] = "poweroff",
index 33c302112e2e6834f41f357d5fc947cae27b8238..d33b9de44d088e8381cdc0ad38c1694fd5145785 100644 (file)
@@ -36,6 +36,9 @@ typedef enum HandleAction {
 #include "logind-inhibit.h"
 #include "logind.h"
 
+/// Additional includes needed by elogind
+#include "elogind-action.h"
+
 int manager_handle_action(
                 Manager *m,
                 InhibitWhat inhibit_key,
@@ -43,8 +46,6 @@ int manager_handle_action(
                 bool ignore_inhibited,
                 bool is_edge);
 
-int shutdown_or_sleep(Manager *m, HandleAction action);
-
 const char* handle_action_to_string(HandleAction h) _const_;
 HandleAction handle_action_from_string(const char *s) _pure_;
 
index 3079d45b94e4ea8d5c873e80abe8af02965c8105..e505fcb0ed987ad0c8f43beb5a2b4b37afc6c940 100644 (file)
@@ -115,8 +115,8 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **
 }
 
 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
-        uid_t uid = 1000;
-        gid_t gid = 1000;
+        uid_t uid;
+        gid_t gid;
         int r;
 
         assert(m);
@@ -345,7 +345,6 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
 
         *user = s->user;
 #endif // 0
-
         return 1;
 }
 
@@ -392,16 +391,16 @@ bool manager_shall_kill(Manager *m, const char *user) {
         assert(m);
         assert(user);
 
-        if (!m->kill_user_processes)
+        if (!m->kill_exclude_users && streq(user, "root"))
                 return false;
 
         if (strv_contains(m->kill_exclude_users, user))
                 return false;
 
-        if (strv_isempty(m->kill_only_users))
-                return true;
+        if (!strv_isempty(m->kill_only_users))
+                return strv_contains(m->kill_only_users, user);
 
-        return strv_contains(m->kill_only_users, user);
+        return m->kill_user_processes;
 }
 
 #if 0 /// UNNEEDED by elogind
@@ -526,7 +525,7 @@ static int manager_count_external_displays(Manager *m) {
                         continue;
 
                 /* Ignore internal displays: the type is encoded in
-                 * the sysfs name, as the second dash seperated item
+                 * the sysfs name, as the second dash separated item
                  * (the first is the card name, the last the connector
                  * number). We implement a whitelist of external
                  * displays here, rather than a whitelist, to ensure
index 10432b2d34e674a2b0dd1738c420aa181ac4e587..26b6c3a92368445f85cdbac946bcf6be79be1e45 100644 (file)
 #include "path-util.h"
 #include "process-util.h"
 #include "selinux-util.h"
-//#include "sleep-config.h"
+#include "sleep-config.h"
 //#include "special.h"
 #include "strv.h"
 #include "terminal-util.h"
 #include "udev-util.h"
 #include "unit-name.h"
 #include "user-util.h"
-//#include "utmp-wtmp.h"
+#include "utmp-wtmp.h"
+
+/// Additional includes needed by elogind
+#include "elogind-dbus.h"
+//#include "update-utmp.h"
 
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
@@ -265,6 +269,42 @@ static int property_get_docked(
         return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
 }
 
+static int property_get_current_sessions(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+
+        assert(bus);
+        assert(reply);
+        assert(m);
+
+        return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
+}
+
+static int property_get_current_inhibitors(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+
+        assert(bus);
+        assert(reply);
+        assert(m);
+
+        return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
+}
+
 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *p = NULL;
         Manager *m = userdata;
@@ -725,6 +765,9 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
             m->seat0->positions[vtnr]->class != SESSION_GREETER)
                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
 
+        if (hashmap_size(m->sessions) >= m->sessions_max)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
+
         audit_session_from_pid(leader, &audit_id);
         if (audit_id > 0) {
                 /* Keep our session IDs and the audit session IDs in sync */
@@ -831,13 +874,17 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
 
         session->create_message = sd_bus_message_ref(message);
 
-        /* Here upstream systemd starts cgroups and the user systemd,
-           and arranges to reply asynchronously.  We reply
-           directly.  */
+#if 0 /// UNNEEDED by elogind
+        /* Now, let's wait until the slice unit and stuff got
+         * created. We send the reply back from
+         * session_send_create_reply(). */
+#else
+        /* We reply directly. */
 
         r = session_send_create_reply(session, NULL);
         if (r < 0)
                 goto fail;
+#endif // 0
 
         return 1;
 
@@ -872,8 +919,9 @@ static int method_release_session(sd_bus_message *message, void *userdata, sd_bu
         if (r < 0)
                 return r;
 
+#if 1 /// elogind must queue this session
         session_add_to_gc_queue(session);
-
+#endif // 1
         return sd_bus_reply_method_return(message, NULL);
 }
 
@@ -1083,11 +1131,11 @@ static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus
 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *cc = NULL;
         Manager *m = userdata;
-        int b, r;
+        int r, b, interactive;
         struct passwd *pw;
         const char *path;
         uint32_t uid;
-        int interactive;
+        bool self = false;
 
         assert(message);
         assert(m);
@@ -1108,6 +1156,8 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
                 if (r < 0)
                         return r;
 
+                self = true;
+
         } else if (!uid_is_valid(uid))
                 return -EINVAL;
 
@@ -1119,7 +1169,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
         r = bus_verify_polkit_async(
                         message,
                         CAP_SYS_ADMIN,
-                        "org.freedesktop.login1.set-user-linger",
+                        self ? "org.freedesktop.login1.set-self-linger" : "org.freedesktop.login1.set-user-linger",
                         NULL,
                         interactive,
                         UID_INVALID,
@@ -1341,6 +1391,7 @@ static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_
         return sd_bus_reply_method_return(message, NULL);
 }
 
+#if 0 /// elogind has its own variant in elogind-dbus.c
 static int have_multiple_sessions(
                 Manager *m,
                 uid_t uid) {
@@ -1363,7 +1414,6 @@ static int have_multiple_sessions(
 static int bus_manager_log_shutdown(
                 Manager *m,
                 InhibitWhat w,
-#if 0 /// elogind does not support systemd units
                 const char *unit_name) {
 
         const char *p, *q;
@@ -1390,38 +1440,7 @@ static int bus_manager_log_shutdown(
                 p = "MESSAGE=System is shutting down";
                 q = NULL;
         }
-#else
-                 HandleAction action) {
-
-         const char *p, *q;
-
-         assert(m);
-
-         if (w != INHIBIT_SHUTDOWN)
-                 return 0;
-
-         switch (action) {
-         case HANDLE_POWEROFF:
-                 p = "MESSAGE=System is powering down.";
-                 q = "SHUTDOWN=power-off";
-                 break;
-         case HANDLE_HALT:
-                 p = "MESSAGE=System is halting.";
-                 q = "SHUTDOWN=halt";
-                 break;
-         case HANDLE_REBOOT:
-                 p = "MESSAGE=System is rebooting.";
-                 q = "SHUTDOWN=reboot";
-                 break;
-         case HANDLE_KEXEC:
-                 p = "MESSAGE=System is rebooting with kexec.";
-                 q = "SHUTDOWN=kexec";
-                 break;
-         default:
-                 p = "MESSAGE=System is shutting down.";
-                 q = NULL;
-         }
-#endif // 0
+
         if (isempty(m->wall_message))
                 p = strjoina(p, ".");
         else
@@ -1433,6 +1452,7 @@ static int bus_manager_log_shutdown(
                           q,
                           NULL);
 }
+#endif // 0
 
 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
         Manager *m = userdata;
@@ -1493,64 +1513,54 @@ static void reset_scheduled_shutdown(Manager *m) {
         }
 }
 
+#if 0 /// elogind has its own variant in elogind-dbus.c
 static int execute_shutdown_or_sleep(
                 Manager *m,
                 InhibitWhat w,
-                HandleAction action,
+                const char *unit_name,
                 sd_bus_error *error) {
 
-#if 0 /// elogind does not need these, we do it ourselves
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         char *c = NULL;
         const char *p;
-#endif // 0
         int r;
 
         assert(m);
         assert(w >= 0);
         assert(w < _INHIBIT_WHAT_MAX);
+        assert(unit_name);
 
-        bus_manager_log_shutdown(m, w, action);
+        bus_manager_log_shutdown(m, w, unit_name);
 
-#if 0 /// elogind does it directly without depending on systemd running the system
         if (m->shutdown_dry_run) {
                 log_info("Running in dry run, suppressing action.");
                 reset_scheduled_shutdown(m);
         } else {
-        r = sd_bus_call_method(
-                        m->bus,
-                        "org.freedesktop.systemd1",
-                        "/org/freedesktop/systemd1",
-                        "org.freedesktop.systemd1.Manager",
-                        "StartUnit",
-                        error,
-                        &reply,
-                        "ss", unit_name, "replace-irreversibly");
-#else
-        r = shutdown_or_sleep(m, action);
-
-        /* no more pending actions, whether this failed or not */
-        m->pending_action = HANDLE_IGNORE;
-        m->action_what    = 0;
-#endif // 0
-        if (r < 0)
-                return r;
+                r = sd_bus_call_method(
+                                m->bus,
+                                "org.freedesktop.systemd1",
+                                "/org/freedesktop/systemd1",
+                                "org.freedesktop.systemd1.Manager",
+                                "StartUnit",
+                                error,
+                                &reply,
+                                "ss", unit_name, "replace-irreversibly");
+                if (r < 0)
+                        return r;
 
-#if 0 /// elogind neither needs a dbus reply, nor supports systemd action jobs
-        r = sd_bus_message_read(reply, "o", &p);
-        if (r < 0)
-                return r;
+                r = sd_bus_message_read(reply, "o", &p);
+                if (r < 0)
+                        return r;
 
-        c = strdup(p);
-        if (!c)
-                return -ENOMEM;
+                c = strdup(p);
+                if (!c)
+                        return -ENOMEM;
         }
 
         m->action_unit = unit_name;
         free(m->action_job);
         m->action_job = c;
         m->action_what = w;
-#endif // 0
 
         /* Make sure the lid switch is ignored for a while */
         manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
@@ -1566,7 +1576,7 @@ int manager_dispatch_delayed(Manager *manager, bool timeout) {
 
         assert(manager);
 
-        if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
+        if (manager->action_what == 0 || manager->action_job)
                 return 0;
 
         if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
@@ -1584,12 +1594,12 @@ int manager_dispatch_delayed(Manager *manager, bool timeout) {
         }
 
         /* Actually do the operation */
-        r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
+        r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
         if (r < 0) {
                 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
 
-                manager->pending_action = HANDLE_IGNORE;
-                manager->action_what    = 0;
+                manager->action_unit = NULL;
+                manager->action_what = 0;
                 return r;
         }
 
@@ -1614,7 +1624,7 @@ static int manager_inhibit_timeout_handler(
 static int delay_shutdown_or_sleep(
                 Manager *m,
                 InhibitWhat w,
-                HandleAction action) {
+                const char *unit_name) {
 
         int r;
         usec_t timeout_val;
@@ -1622,6 +1632,7 @@ static int delay_shutdown_or_sleep(
         assert(m);
         assert(w >= 0);
         assert(w < _INHIBIT_WHAT_MAX);
+        assert(unit_name);
 
         timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
 
@@ -1640,7 +1651,7 @@ static int delay_shutdown_or_sleep(
                         return r;
         }
 
-        m->pending_action = action;
+        m->action_unit = unit_name;
         m->action_what = w;
 
         return 0;
@@ -1670,7 +1681,7 @@ static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
 
 int bus_manager_shutdown_or_sleep_now_or_later(
                 Manager *m,
-                HandleAction action,
+                const char *unit_name,
                 InhibitWhat w,
                 sd_bus_error *error) {
 
@@ -1678,8 +1689,10 @@ int bus_manager_shutdown_or_sleep_now_or_later(
         int r;
 
         assert(m);
+        assert(unit_name);
         assert(w >= 0);
         assert(w <= _INHIBIT_WHAT_MAX);
+        assert(!m->action_job);
 
         /* Tell everybody to prepare for shutdown/sleep */
         send_prepare_for(m, w, true);
@@ -1688,14 +1701,17 @@ int bus_manager_shutdown_or_sleep_now_or_later(
                 m->inhibit_delay_max > 0 &&
                 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
 
+        log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
+                          handle_action_to_string(action),
+                          delayed ? "" : "NOT ");
         if (delayed)
                 /* Shutdown is delayed, keep in mind what we
                  * want to do, and start a timeout */
-                r = delay_shutdown_or_sleep(m, w, action);
+                r = delay_shutdown_or_sleep(m, w, unit_name);
         else
                 /* Shutdown is not delayed, execute it
                  * immediately */
-                r = execute_shutdown_or_sleep(m, w, action, error);
+                r = execute_shutdown_or_sleep(m, w, unit_name, error);
 
         return r;
 }
@@ -1765,7 +1781,7 @@ static int verify_shutdown_creds(
 static int method_do_shutdown_or_sleep(
                 Manager *m,
                 sd_bus_message *message,
-                HandleAction sleep_action,
+                const char *unit_name,
                 InhibitWhat w,
                 const char *action,
                 const char *action_multiple_sessions,
@@ -1777,6 +1793,7 @@ static int method_do_shutdown_or_sleep(
 
         assert(m);
         assert(message);
+        assert(unit_name);
         assert(w >= 0);
         assert(w <= _INHIBIT_WHAT_MAX);
 
@@ -1784,12 +1801,15 @@ static int method_do_shutdown_or_sleep(
         if (r < 0)
                 return r;
 
+        log_debug_elogind("%s called with action '%s', sleep '%s' (%sinteractive)",
+                          __FUNCTION__, action, sleep_verb,
+                          interactive ? "" : "NOT ");
         /* Don't allow multiple jobs being executed at the same time */
         if (m->action_what)
                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
 
         if (sleep_verb) {
-                r = can_sleep(m, sleep_verb);
+                r = can_sleep(sleep_verb);
                 if (r < 0)
                         return r;
 
@@ -1799,10 +1819,11 @@ static int method_do_shutdown_or_sleep(
 
         r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
                                   action_ignore_inhibit, error);
+        log_debug_elogind("verify_shutdown_creds() returned %d", r);
         if (r != 0)
                 return r;
 
-        r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error);
+        r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
         if (r < 0)
                 return r;
 
@@ -1812,9 +1833,10 @@ static int method_do_shutdown_or_sleep(
 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
+        log_debug_elogind("%s called", __FUNCTION__);
         return method_do_shutdown_or_sleep(
                         m, message,
-                        HANDLE_POWEROFF,
+                        SPECIAL_POWEROFF_TARGET,
                         INHIBIT_SHUTDOWN,
                         "org.freedesktop.login1.power-off",
                         "org.freedesktop.login1.power-off-multiple-sessions",
@@ -1826,9 +1848,10 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error
 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
+        log_debug_elogind("%s called", __FUNCTION__);
         return method_do_shutdown_or_sleep(
                         m, message,
-                        HANDLE_REBOOT,
+                        SPECIAL_REBOOT_TARGET,
                         INHIBIT_SHUTDOWN,
                         "org.freedesktop.login1.reboot",
                         "org.freedesktop.login1.reboot-multiple-sessions",
@@ -1840,9 +1863,10 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
+        log_debug_elogind("%s called", __FUNCTION__);
         return method_do_shutdown_or_sleep(
                         m, message,
-                        HANDLE_SUSPEND,
+                        SPECIAL_SUSPEND_TARGET,
                         INHIBIT_SLEEP,
                         "org.freedesktop.login1.suspend",
                         "org.freedesktop.login1.suspend-multiple-sessions",
@@ -1850,6 +1874,7 @@ static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error
                         "suspend",
                         error);
 }
+#endif // 0
 
 static int nologin_timeout_handler(
                         sd_event_source *s,
@@ -1919,12 +1944,13 @@ static int update_schedule_file(Manager *m) {
         return 0;
 
 fail:
-                (void) unlink(temp_path);
-                (void) unlink("/run/systemd/shutdown/scheduled");
+        (void) unlink(temp_path);
+        (void) unlink("/run/systemd/shutdown/scheduled");
 
         return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
 }
 
+#if 0 /// elogind has its own variant in elogind-dbus.c
 static int manager_scheduled_shutdown_handler(
                         sd_event_source *s,
                         uint64_t usec,
@@ -1932,7 +1958,7 @@ static int manager_scheduled_shutdown_handler(
 
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         Manager *m = userdata;
-        HandleAction action;
+        const char *target;
         int r;
 
         assert(m);
@@ -1941,18 +1967,19 @@ static int manager_scheduled_shutdown_handler(
                 return 0;
 
         if (streq(m->scheduled_shutdown_type, "halt"))
-                action = HANDLE_HALT;
+                target = SPECIAL_HALT_TARGET;
         else if (streq(m->scheduled_shutdown_type, "poweroff"))
-                action = HANDLE_POWEROFF;
+                target = SPECIAL_POWEROFF_TARGET;
         else
-                action = HANDLE_REBOOT;
+                target = SPECIAL_REBOOT_TARGET;
 
-        r = execute_shutdown_or_sleep(m, 0, action, &error);
+        r = execute_shutdown_or_sleep(m, 0, target, &error);
         if (r < 0)
-                return log_error_errno(r, "Unable to execute transition to %s: %m", m->scheduled_shutdown_type);
+                return log_error_errno(r, "Unable to execute transition to %s: %m", target);
 
         return 0;
 }
+#endif // 0
 
 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
@@ -1967,6 +1994,7 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
         assert(m);
         assert(message);
 
+        log_debug_elogind("%s called", __FUNCTION__);
         r = sd_bus_message_read(message, "st", &type, &elapse);
         if (r < 0)
                 return r;
@@ -2048,11 +2076,9 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
                 }
         }
 
-#if 0 /// elogind does not support utmp-wtmp
         r = manager_setup_wall_message_timer(m);
         if (r < 0)
                 return r;
-#endif // 0
 
         if (!isempty(type)) {
                 r = update_schedule_file(m);
@@ -2067,14 +2093,17 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         bool cancelled;
+#if 1 /// elogind needs to construct the message to allow extra wall messages
+        _cleanup_free_ char *l = NULL;
+#endif // 1
 
         assert(m);
         assert(message);
 
+        log_debug_elogind("%s called", __FUNCTION__);
         cancelled = m->scheduled_shutdown_type != NULL;
         reset_scheduled_shutdown(m);
 
-#if 0 /// elogind does not support utmp-wtmp
         if (cancelled) {
                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 const char *tty = NULL;
@@ -2087,20 +2116,33 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
                         (void) sd_bus_creds_get_tty(creds, &tty);
                 }
 
+#if 0 /// elogind wants to allow extra cancellation messages
                 utmp_wall("The system shutdown has been cancelled",
                           uid_to_name(uid), tty, logind_wall_tty_filter, m);
-        }
+#else
+                r = asprintf(&l, "%s%sThe system shutdown has been cancelled!",
+                             strempty(m->wall_message),
+                             isempty(m->wall_message) ? "" : "\n");
+                if (r < 0) {
+                        log_oom();
+                        return 0;
+                }
+
+                utmp_wall(l, uid_to_name(uid), tty, logind_wall_tty_filter, m);
 #endif // 0
+        }
 
         return sd_bus_reply_method_return(message, "b", cancelled);
 }
 
+#if 0 /// elogind has its own variant in elogind-dbus.c
 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
+        log_debug_elogind("%s called", __FUNCTION__);
         return method_do_shutdown_or_sleep(
                         m, message,
-                        HANDLE_HIBERNATE,
+                        SPECIAL_HIBERNATE_TARGET,
                         INHIBIT_SLEEP,
                         "org.freedesktop.login1.hibernate",
                         "org.freedesktop.login1.hibernate-multiple-sessions",
@@ -2112,9 +2154,10 @@ static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_erro
 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
 
+        log_debug_elogind("%s called", __FUNCTION__);
         return method_do_shutdown_or_sleep(
                         m, message,
-                        HANDLE_HYBRID_SLEEP,
+                        SPECIAL_HYBRID_SLEEP_TARGET,
                         INHIBIT_SLEEP,
                         "org.freedesktop.login1.hibernate",
                         "org.freedesktop.login1.hibernate-multiple-sessions",
@@ -2122,6 +2165,7 @@ static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_e
                         "hybrid-sleep",
                         error);
 }
+#endif // 0
 
 static int method_can_shutdown_or_sleep(
                 Manager *m,
@@ -2148,7 +2192,11 @@ static int method_can_shutdown_or_sleep(
         assert(action_ignore_inhibit);
 
         if (sleep_verb) {
+#if 0 /// elogind needs to have the manager being passed
+                r = can_sleep(sleep_verb);
+#else
                 r = can_sleep(m, sleep_verb);
+#endif // 0
                 if (r < 0)
                         return r;
                 if (r == 0)
@@ -2301,7 +2349,7 @@ static int property_get_reboot_to_firmware_setup(
 
         return sd_bus_message_append(reply, "b", r > 0);
 #else
-        return sd_bus_message_append(reply, "b", -EOPNOTSUPP);
+        return sd_bus_message_append(reply, "b", false);
 #endif // 0
 }
 
@@ -2381,7 +2429,7 @@ static int method_can_reboot_to_firmware_setup(
 
         return sd_bus_reply_method_return(message, "s", result);
 #else
-        return sd_bus_reply_method_return(message, "s", "na");
+        return sd_bus_reply_method_return(message, "s", "no");
 #endif // 0
 }
 
@@ -2402,6 +2450,7 @@ static int method_set_wall_message(
         if (r < 0)
                 return r;
 
+#if 0 /// elogind only calls this for shutdown/reboot, which already needs authorization.
         r = bus_verify_polkit_async(message,
                                     CAP_SYS_ADMIN,
                                     "org.freedesktop.login1.set-wall-message",
@@ -2414,6 +2463,7 @@ static int method_set_wall_message(
                 return r;
         if (r == 0)
                 return 1; /* Will call us back */
+#endif // 0
 
         if (isempty(wall_message))
                 m->wall_message = mfree(m->wall_message);
@@ -2499,6 +2549,9 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error
         if (r < 0)
                 return r;
 
+        if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
+
         do {
                 id = mfree(id);
 
@@ -2546,7 +2599,9 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
         SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
 
-//        SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
+#if 0 /// UNNEEDED by elogind
+        SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
+#endif // 0
         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -2569,6 +2624,13 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
         SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
         SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
+        SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
+        SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
+        SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
 
         SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2842,6 +2904,7 @@ int manager_start_slice(
 
         assert(manager);
         assert(slice);
+        assert(job);
 
         r = sd_bus_message_new_method_call(
                         manager->bus,
@@ -2895,9 +2958,7 @@ int manager_start_slice(
         if (r < 0)
                 return r;
 
-        if (job)
-                return strdup_job(reply, job);
-        return 1;
+        return strdup_job(reply, job);
 }
 
 int manager_start_scope(
@@ -2918,6 +2979,7 @@ int manager_start_scope(
         assert(manager);
         assert(scope);
         assert(pid > 1);
+        assert(job);
 
         r = sd_bus_message_new_method_call(
                         manager->bus,
@@ -2992,9 +3054,7 @@ int manager_start_scope(
         if (r < 0)
                 return r;
 
-        if (job)
-                return strdup_job(reply, job);
-        return 1;
+        return strdup_job(reply, job);
 }
 
 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
@@ -3003,6 +3063,7 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error,
 
         assert(manager);
         assert(unit);
+        assert(job);
 
         r = sd_bus_call_method(
                         manager->bus,
@@ -3016,9 +3077,7 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error,
         if (r < 0)
                 return r;
 
-        if (job)
-                return strdup_job(reply, job);
-        return 1;
+        return strdup_job(reply, job);
 }
 
 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
@@ -3027,6 +3086,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c
 
         assert(manager);
         assert(unit);
+        assert(job);
 
         r = sd_bus_call_method(
                         manager->bus,
@@ -3041,9 +3101,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c
                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
 
-                        if (job)
-                                *job = NULL;
-
+                        *job = NULL;
                         sd_bus_error_free(error);
                         return 0;
                 }
@@ -3051,9 +3109,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c
                 return r;
         }
 
-        if (job)
-                return strdup_job(reply, job);
-        return 1;
+        return strdup_job(reply, job);
 }
 
 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
index 9705dd5b13a2324d75838045f2d21fd50eafbf8c..c7f54b5f5df8e3e9f2af0543d337125b0221e888 100644 (file)
@@ -32,6 +32,9 @@ Login.IdleAction,                  config_parse_handle_action, 0, offsetof(Manag
 Login.IdleActionSec,               config_parse_sec,           0, offsetof(Manager, idle_action_usec)
 Login.RuntimeDirectorySize,        config_parse_tmpfs_size,    0, offsetof(Manager, runtime_dir_size)
 Login.RemoveIPC,                   config_parse_bool,          0, offsetof(Manager, remove_ipc)
+Login.InhibitorsMax,               config_parse_uint64,        0, offsetof(Manager, inhibitors_max)
+Login.SessionsMax,                 config_parse_uint64,        0, offsetof(Manager, sessions_max)
+Login.UserTasksMax,                config_parse_user_tasks_max,0, offsetof(Manager, user_tasks_max)
 Sleep.SuspendMode,                 config_parse_strv,          0, offsetof(Manager, suspend_mode)
 Sleep.SuspendState,                config_parse_strv,          0, offsetof(Manager, suspend_state)
 Sleep.HibernateMode,               config_parse_strv,          0, offsetof(Manager, hibernate_mode)
index a0e3ba2b7cd20e3df8547ae3d11381244335377f..6c78e0dddc9f0d8e255a2e2b2d0614001750084a 100644 (file)
@@ -317,7 +317,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
                 if (r < 0)
                         return r;
 
-                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE);
+                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE-10);
                 if (r < 0)
                         return r;
         }
index 3cee10d009a155c6a8d5f161dc8d2035a82dc01b..f934a5326a2edc11ef237b85215a17522f895d2b 100644 (file)
@@ -306,7 +306,7 @@ const sd_bus_vtable seat_vtable[] = {
         SD_BUS_PROPERTY("CanMultiSession", "b", property_get_can_multi_session, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
-        SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0),
         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
index 33fd3afacae4ff38af25d10fc71fa4205dc4cbdc..ae42811dea4d12dcc3242fb5361cab4e09525424 100644 (file)
@@ -368,7 +368,6 @@ int seat_active_vt_changed(Seat *s, unsigned int vtnr) {
         }
 
         r = seat_set_active(s, new_active);
-
 #if 0 /// elogind does not spawn autovt
         manager_spawn_autovt(s->manager, vtnr);
 #endif // 0
index 848e2721859bc3b1fde90c53cb7a88ad4dd6b767..d5174339327cafe46dd3b689e1243eba28a32109 100644 (file)
@@ -28,6 +28,7 @@
 #include "logind-session-device.h"
 #include "logind-session.h"
 #include "logind.h"
+#include "signal-util.h"
 #include "strv.h"
 #include "util.h"
 
@@ -179,6 +180,24 @@ static int property_get_idle_since_hint(
         return sd_bus_message_append(reply, "t", u);
 }
 
+static int property_get_locked_hint(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Session *s = userdata;
+
+        assert(bus);
+        assert(reply);
+        assert(s);
+
+        return sd_bus_message_append(reply, "b", session_get_locked_hint(s) > 0);
+}
+
 int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Session *s = userdata;
         int r;
@@ -278,6 +297,35 @@ static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_
         return sd_bus_reply_method_return(message, NULL);
 }
 
+static int method_set_locked_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+        Session *s = userdata;
+        uid_t uid;
+        int r, b;
+
+        assert(message);
+        assert(s);
+
+        r = sd_bus_message_read(message, "b", &b);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_creds_get_euid(creds, &uid);
+        if (r < 0)
+                return r;
+
+        if (uid != 0 && uid != s->user->uid)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint");
+
+        session_set_locked_hint(s, b);
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
 int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Session *s = userdata;
         const char *swho;
@@ -300,7 +348,7 @@ int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
         }
 
-        if (signo <= 0 || signo >= _NSIG)
+        if (!SIGNAL_VALID(signo))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
 
         r = bus_verify_polkit_async(
@@ -486,12 +534,14 @@ const sd_bus_vtable session_vtable[] = {
         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
 
         SD_BUS_METHOD("Terminate", NULL, NULL, bus_session_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("Lock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("Unlock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("SetLockedHint", "b", NULL, method_set_locked_hint, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -718,10 +768,9 @@ int session_send_create_reply(Session *s, sd_bus_error *error) {
         if (fifo_fd < 0)
                 return fifo_fd;
 
-        /* Update the session and user state files before we notify
-         * the client about the result. */
+        /* Update the session state file before we notify the client
+         * about the result. */
         session_save(s);
-        user_save(s->user);
 
         p = session_bus_path(s);
         if (!p)
index 4055a23277391abaee3588fae11b08aa91b5ec42..6c65607b9fd9fd0808140af50f793162446bf86f 100644 (file)
 #include <sys/ioctl.h>
 #include <sys/types.h>
 
+#if 0 /// elogind needs the systems udev header
 #include "libudev.h"
+#else
+#include <libudev.h>
+#endif // 0
 
 #include "alloc-util.h"
 #include "bus-util.h"
index c37e87565921dd634fb175cdaafe644e045f53e8..06ad99e1fec4eaeb6d0488de1bc4e6a0b6ca99b7 100644 (file)
@@ -46,7 +46,7 @@
 #include "user-util.h"
 #include "util.h"
 
-// #define RELEASE_USEC (20*USEC_PER_SEC)
+#define RELEASE_USEC (20*USEC_PER_SEC)
 
 static void session_remove_fifo(Session *s);
 
@@ -452,17 +452,10 @@ int session_load(Session *s) {
                 safe_close(fd);
         }
 
-        if (realtime) {
-                unsigned long long l;
-                if (sscanf(realtime, "%llu", &l) > 0)
-                        s->timestamp.realtime = l;
-        }
-
-        if (monotonic) {
-                unsigned long long l;
-                if (sscanf(monotonic, "%llu", &l) > 0)
-                        s->timestamp.monotonic = l;
-        }
+        if (realtime)
+                timestamp_deserialize(realtime, &s->timestamp.realtime);
+        if (monotonic)
+                timestamp_deserialize(monotonic, &s->timestamp.monotonic);
 
         if (controller) {
                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
@@ -527,7 +520,7 @@ static int session_start_scope(Session *s) {
                 if (!scope)
                         return log_oom();
 
-                description = strjoina("Session ", s->id, " of user ", s->user->name, NULL);
+                description = strjoina("Session ", s->id, " of user ", s->user->name);
 
                 r = manager_start_scope(
                                 s->manager,
@@ -557,8 +550,7 @@ static int session_start_scope(Session *s) {
 
         return 0;
 }
-#endif // 0
-
+#else
 static int session_start_cgroup(Session *s) {
         int r;
 
@@ -577,7 +569,7 @@ static int session_start_cgroup(Session *s) {
 
         return 0;
 }
-
+#endif // 0
 
 int session_start(Session *s) {
         int r;
@@ -595,9 +587,7 @@ int session_start(Session *s) {
                 return r;
 
         /* Create cgroup */
-/// elogind does its own session management without systemd units,
-/// slices and scopes
-#if 0
+#if 0 /// elogind does its own session management
         r = session_start_scope(s);
 #else
         r = session_start_cgroup(s);
@@ -645,7 +635,6 @@ int session_start(Session *s) {
 #if 0 /// UNNEEDED by elogind
 static int session_stop_scope(Session *s, bool force) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        char *job = NULL;
         int r;
 
         assert(s);
@@ -653,27 +642,29 @@ static int session_stop_scope(Session *s, bool force) {
         if (!s->scope)
                 return 0;
 
+        /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
+         * that is left in in the scope is "left-over". Informing systemd about this has the benefit that it will log
+         * when killing any processes left after this point. */
+        r = manager_abandon_scope(s->manager, s->scope, &error);
+        if (r < 0)
+                log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
+
+        /* Optionally, let's kill everything that's left now. */
         if (force || manager_shall_kill(s->manager, s->user->name)) {
+                char *job = NULL;
+
                 r = manager_stop_unit(s->manager, s->scope, &error, &job);
-                if (r < 0) {
-                        log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
-                        return r;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
 
                 free(s->scope_job);
                 s->scope_job = job;
-        } else {
-                r = manager_abandon_scope(s->manager, s->scope, &error);
-                if (r < 0) {
-                        log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
-                        return r;
-                }
-        }
+        } else
+                s->scope_job = mfree(s->scope_job);
 
         return 0;
 }
-#endif // 0
-
+#else
 static int session_stop_cgroup(Session *s, bool force) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
@@ -688,6 +679,7 @@ static int session_stop_cgroup(Session *s, bool force) {
 
         return 0;
 }
+#endif // 0
 
 int session_stop(Session *s, bool force) {
         int r;
@@ -792,17 +784,16 @@ int session_release(Session *s) {
         if (s->timer_event_source)
                 return 0;
 
-        /* In systemd, session release is triggered by user jobs
-           dying.  In elogind we don't have that so go ahead and stop
-           now.  */
-#if 0
+#if 0 /// UNNEEDED by elogind
         return sd_event_add_time(s->manager->event,
                                  &s->timer_event_source,
                                  CLOCK_MONOTONIC,
                                  now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
                                  release_timeout_callback, s);
-
 #else
+        /* In systemd, session release is triggered by user jobs
+           dying.  In elogind we don't have that so go ahead and stop
+           now.  */
         return session_stop(s, false);
 #endif // 0
 }
@@ -869,7 +860,7 @@ int session_get_idle_hint(Session *s, dual_timestamp *t) {
 
         /* Graphical sessions should really implement a real
          * idle hint logic */
-        if (s->display)
+        if (SESSION_TYPE_IS_GRAPHICAL(s->type))
                 goto dont_know;
 
         /* For sessions with an explicitly configured tty, let's check
@@ -924,6 +915,23 @@ void session_set_idle_hint(Session *s, bool b) {
         manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
 }
 
+int session_get_locked_hint(Session *s) {
+        assert(s);
+
+        return s->locked_hint;
+}
+
+void session_set_locked_hint(Session *s, bool b) {
+        assert(s);
+
+        if (s->locked_hint == b)
+                return;
+
+        s->locked_hint = b;
+
+        session_send_changed(s, "LockedHint", NULL);
+}
+
 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
         Session *s = userdata;
 
@@ -969,7 +977,9 @@ int session_create_fifo(Session *s) {
                 if (r < 0)
                         return r;
 
-                r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
+                /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
+                 * sessions). */
+                r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
                 if (r < 0)
                         return r;
         }
@@ -1016,10 +1026,6 @@ bool session_check_gc(Session *s, bool drop_not_started) {
                 return true;
 #endif // 0
 
-        if ( s->user->manager
-          && (cg_is_empty_recursive (SYSTEMD_CGROUP_CONTROLLER, s->user->manager->cgroup_root) > 0) )
-                return true;
-
         return false;
 }
 
@@ -1072,13 +1078,10 @@ int session_kill(Session *s, KillWho who, int signo) {
                         return log_error_errno(errno, "Failed to kill process leader %d for session %s: %m", s->leader, s->id);
                 }
                 return 0;
-        } else {
-                bool sigcont = false;
-                bool ignore_self = true;
-                bool rem = true;
+        } else
                 return cg_kill_recursive (SYSTEMD_CGROUP_CONTROLLER, s->id, signo,
-                                          sigcont, ignore_self, rem, NULL);
-        }
+                                          CGROUP_IGNORE_SELF | CGROUP_REMOVE,
+                                          NULL, NULL, NULL);
 #endif // 0
 }
 
index b315f01dcb63a9843c5fb68b21632d5dabe7a0a4..d86ba61ad0c1ba0e904a782f7b279c48f3874d48 100644 (file)
@@ -87,7 +87,6 @@ struct Session {
         char *service;
         char *desktop;
 
-        /* always NULL */
         char *scope;
 #if 0 /// UNNEEDED by elogind
         char *scope_job;
@@ -108,6 +107,8 @@ struct Session {
         bool idle_hint;
         dual_timestamp idle_hint_timestamp;
 
+        bool locked_hint;
+
         bool in_gc_queue:1;
         bool started:1;
         bool stopping:1;
@@ -135,6 +136,8 @@ int session_activate(Session *s);
 bool session_is_active(Session *s);
 int session_get_idle_hint(Session *s, dual_timestamp *t);
 void session_set_idle_hint(Session *s, bool b);
+int session_get_locked_hint(Session *s);
+void session_set_locked_hint(Session *s, bool b);
 int session_create_fifo(Session *s);
 int session_start(Session *s);
 int session_stop(Session *s, bool force);
index fd98c7becafb800daeb3f7ada0f8d8e06484a8ea..af6392e02570ec8ac5a9985f418179ed2a383d88 100644 (file)
@@ -25,6 +25,7 @@
 #include "formats-util.h"
 #include "logind-user.h"
 #include "logind.h"
+#include "signal-util.h"
 #include "strv.h"
 #include "user-util.h"
 
@@ -222,7 +223,7 @@ int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *
         if (r < 0)
                 return r;
 
-        if (signo <= 0 || signo >= _NSIG)
+        if (!SIGNAL_VALID(signo))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
 
         r = user_kill(u, signo);
@@ -244,7 +245,7 @@ const sd_bus_vtable user_vtable[] = {
         SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
-        SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0),
         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
index b6daf65296920c8285e903ddd2506002f988c828..171a4a670e7222530bce43830a6f0cdd95b5f6a1 100644 (file)
 #include "user-util.h"
 #include "util.h"
 
+#if 1 /// elogind uses a static value here
+#  define SPECIAL_USER_SLICE "user.slice"
+#endif // 1
+
 int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
         _cleanup_(user_freep) User *u = NULL;
         char lu[DECIMAL_STR_MAX(uid_t) + 1];
@@ -77,7 +81,7 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
         if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0)
                 return -ENOMEM;
 
-        r = slice_build_subslice("user.slice", lu, &u->slice);
+        r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
         if (r < 0)
                 return r;
 
@@ -124,6 +128,7 @@ User *user_free(User *u) {
         u->slice_job = mfree(u->slice_job);
         u->service_job = mfree(u->service_job);
 #endif // 0
+
         u->service = mfree(u->service);
         u->slice = mfree(u->slice);
         u->runtime_path = mfree(u->runtime_path);
@@ -316,8 +321,7 @@ int user_load(User *u) {
                 if (r == -ENOENT)
                         return 0;
 
-                log_error_errno(r, "Failed to read %s: %m", u->state_file);
-                return r;
+                return log_error_errno(r, "Failed to read %s: %m", u->state_file);
         }
 
         if (display)
@@ -326,17 +330,10 @@ int user_load(User *u) {
         if (s && s->display && display_is_local(s->display))
                 u->display = s;
 
-        if (realtime) {
-                unsigned long long l;
-                if (sscanf(realtime, "%llu", &l) > 0)
-                        u->timestamp.realtime = l;
-        }
-
-        if (monotonic) {
-                unsigned long long l;
-                if (sscanf(monotonic, "%llu", &l) > 0)
-                        u->timestamp.monotonic = l;
-        }
+        if (realtime)
+                timestamp_deserialize(realtime, &u->timestamp.realtime);
+        if (monotonic)
+                timestamp_deserialize(monotonic, &u->timestamp.monotonic);
 
         return r;
 }
@@ -390,7 +387,7 @@ static int user_mkdir_runtime_path(User *u) {
         return 0;
 
 fail:
-                /* Try to clean up, but ignore errors */
+        /* Try to clean up, but ignore errors */
         (void) rmdir(u->runtime_path);
         return r;
 }
@@ -446,11 +443,11 @@ static int user_start_service(User *u) {
                         u->service,
                         &error,
                         &job);
-                if (r < 0) {
+        if (r < 0) {
                 /* we don't fail due to this, let's try to continue */
                 log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r));
-                } else {
-                        u->service_job = job;
+        } else {
+                u->service_job = job;
         }
 #else
         assert(u);
@@ -892,7 +889,6 @@ int config_parse_tmpfs_size(
                 void *userdata) {
 
         size_t *sz = data;
-        const char *e;
         int r;
 
         assert(filename);
@@ -900,35 +896,68 @@ int config_parse_tmpfs_size(
         assert(rvalue);
         assert(data);
 
-        e = endswith(rvalue, "%");
-        if (e) {
-                unsigned long ul;
-                char *f;
+        /* First, try to parse as percentage */
+        r = parse_percent(rvalue);
+        if (r > 0 && r < 100)
+                *sz = physical_memory_scale(r, 100U);
+        else {
+                uint64_t k;
 
-                errno = 0;
-                ul = strtoul(rvalue, &f, 10);
-                if (errno > 0 || f != e) {
-                        log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse percentage value, ignoring: %s", rvalue);
-                        return 0;
-                }
+                /* If the passed argument was not a percentage, or out of range, parse as byte size */
 
-                if (ul <= 0 || ul >= 100) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Percentage value out of range, ignoring: %s", rvalue);
+                r = parse_size(rvalue, 1024, &k);
+                if (r < 0 || k <= 0 || (uint64_t) (size_t) k != k) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
                         return 0;
                 }
 
-                *sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100));
-        } else {
-                uint64_t k;
+                *sz = PAGE_ALIGN((size_t) k);
+        }
 
-                r = parse_size(rvalue, 1024, &k);
-                if (r < 0 || (uint64_t) (size_t) k != k) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
+        return 0;
+}
+
+int config_parse_user_tasks_max(
+                const char* unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        uint64_t *m = data;
+        uint64_t k;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        /* First, try to parse as percentage */
+        r = parse_percent(rvalue);
+        if (r >= 0)
+                k = system_tasks_max_scale(r, 100U);
+        else {
+
+                /* If the passed argument was not a percentage, or out of range, parse as byte size */
+
+                r = safe_atou64(rvalue, &k);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse tasks maximum, ignoring: %s", rvalue);
                         return 0;
                 }
+        }
 
-                *sz = PAGE_ALIGN((size_t) k);
+        if (k <= 0 || k >= UINT64_MAX) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Tasks maximum out of range, ignoring: %s", rvalue);
+                return 0;
         }
 
+        *m = k;
         return 0;
 }
index f3fa4403d8284da07f40b6e3b338aefbfb405f68..043870b2417d8352c836a4af68b665e6e8e54499 100644 (file)
@@ -42,14 +42,9 @@ struct User {
         char *name;
         char *state_file;
         char *runtime_path;
-
-        /* These are always NULL, and here just for logind-user-dbus.c
-           to easily provide a NULL value for the user's service and
-           slice properties. */
         char *slice;
         char *service;
 
-
 #if 0 /// UNNEEDED by elogind
         char *service_job;
         char *slice_job;
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
new file mode 100644 (file)
index 0000000..917aa72
--- /dev/null
@@ -0,0 +1,210 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Daniel Mack
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <pwd.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "sd-messages.h"
+
+#include "alloc-util.h"
+#include "audit-util.h"
+#include "bus-common-errors.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "formats-util.h"
+#include "logind.h"
+//#include "special.h"
+#include "strv.h"
+#include "unit-name.h"
+#include "user-util.h"
+#include "utmp-wtmp.h"
+
+_const_ static usec_t when_wall(usec_t n, usec_t elapse) {
+
+        usec_t left;
+        unsigned int i;
+        static const int wall_timers[] = {
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+                25, 40, 55, 70, 100, 130, 150, 180,
+        };
+
+        /* If the time is already passed, then don't announce */
+        if (n >= elapse)
+                return 0;
+
+        left = elapse - n;
+
+        for (i = 1; i < ELEMENTSOF(wall_timers); i++)
+                if (wall_timers[i] * USEC_PER_MINUTE >= left)
+                        return left - wall_timers[i-1] * USEC_PER_MINUTE;
+
+        return left % USEC_PER_HOUR;
+}
+
+bool logind_wall_tty_filter(const char *tty, void *userdata) {
+
+        Manager *m = userdata;
+
+        assert(m);
+
+        if (!startswith(tty, "/dev/") || !m->scheduled_shutdown_tty)
+                return true;
+
+        return !streq(tty + 5, m->scheduled_shutdown_tty);
+}
+
+static int warn_wall(Manager *m, usec_t n) {
+        char date[FORMAT_TIMESTAMP_MAX] = {};
+        _cleanup_free_ char *l = NULL;
+        bool left;
+        int r;
+
+        assert(m);
+
+        if (!m->enable_wall_messages)
+                return 0;
+
+        left = m->scheduled_shutdown_timeout > n;
+
+        r = asprintf(&l, "%s%sThe system is going down for %s %s%s!",
+                     strempty(m->wall_message),
+                     isempty(m->wall_message) ? "" : "\n",
+                     m->scheduled_shutdown_type,
+                     left ? "at " : "NOW",
+                     left ? format_timestamp(date, sizeof(date), m->scheduled_shutdown_timeout) : "");
+        if (r < 0) {
+                log_oom();
+                return 0;
+        }
+
+        utmp_wall(l, uid_to_name(m->scheduled_shutdown_uid),
+                  m->scheduled_shutdown_tty, logind_wall_tty_filter, m);
+
+        return 1;
+}
+
+static int wall_message_timeout_handler(
+                        sd_event_source *s,
+                        uint64_t usec,
+                        void *userdata) {
+
+        Manager *m = userdata;
+        usec_t n, next;
+        int r;
+
+        assert(m);
+        assert(s == m->wall_message_timeout_source);
+
+        n = now(CLOCK_REALTIME);
+
+        r = warn_wall(m, n);
+        if (r == 0)
+                return 0;
+
+        next = when_wall(n, m->scheduled_shutdown_timeout);
+        if (next > 0) {
+                r = sd_event_source_set_time(s, n + next);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_source_set_time() failed. %m");
+
+                r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_source_set_enabled() failed. %m");
+        }
+
+        return 0;
+}
+
+int manager_setup_wall_message_timer(Manager *m) {
+
+        usec_t n, elapse;
+#if 1 /// let's fix double wall messages in elogind - they suck.
+        usec_t left;
+#endif // 1
+        int r;
+
+        assert(m);
+
+#if 1 /// Make elogind more aware of the possibility to disable wall messages
+        /* Do not do anything if wall messages aren't enabled */
+        if (!m->enable_wall_messages)
+                return 0;
+#endif // 1
+
+        n = now(CLOCK_REALTIME);
+        elapse = m->scheduled_shutdown_timeout;
+
+        /* wall message handling */
+
+        if (isempty(m->scheduled_shutdown_type)) {
+                warn_wall(m, n);
+                return 0;
+        }
+
+        if (elapse < n)
+                return 0;
+
+#if 0 /// let's fix double wall messages in elogind - they suck.
+        /* Warn immediately if less than 15 minutes are left */
+        if (elapse - n < 15 * USEC_PER_MINUTE) {
+                r = warn_wall(m, n);
+                if (r == 0)
+                        return 0;
+        }
+
+        elapse = when_wall(n, elapse);
+        if (elapse == 0)
+                return 0;
+#else
+        left = elapse - n;
+        elapse = when_wall(n, elapse);
+
+        /* Warn immediately if less than 15 minutes are left, but not if
+         * there aren't more than three seconds to the next timeout. */
+        if ( (left   < 15 * USEC_PER_MINUTE)
+          && (elapse >  3 * USEC_PER_SEC) ) {
+                r = warn_wall(m, n);
+                if (r == 0)
+                        return 0;
+        }
+
+        /* If the next timeout is within on second, delay it by 3 seconds */
+        if (USEC_PER_SEC > elapse)
+                elapse = 3 * USEC_PER_SEC;
+#endif // 0
+
+        if (m->wall_message_timeout_source) {
+                r = sd_event_source_set_time(m->wall_message_timeout_source, n + elapse);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_source_set_time() failed. %m");
+
+                r = sd_event_source_set_enabled(m->wall_message_timeout_source, SD_EVENT_ONESHOT);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_source_set_enabled() failed. %m");
+        } else {
+                r = sd_event_add_time(m->event, &m->wall_message_timeout_source,
+                                      CLOCK_REALTIME, n + elapse, 0, wall_message_timeout_handler, m);
+                if (r < 0)
+                        return log_error_errno(r, "sd_event_add_time() failed. %m");
+        }
+
+        return 0;
+}
index 59fe591447f28fb12f75269a204693e3bcba7305..dab6e7f443d016cf23ca42cc9879222f384e4caa 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
+#if 0 /// elogind needs the systems udev header
 #include "libudev.h"
+#else
+#include <libudev.h>
+#endif // 0
 #include "sd-daemon.h"
 
 #include "alloc-util.h"
 #include "strv.h"
 #include "udev-util.h"
 
-/// additional includes elogind needs
+/// Additional includes needed by elogind
 #include "cgroup.h"       // From src/core/
+#include "elogind.h"
 #include "label.h"
-#include "mount-setup.h"  // From src/core
 #include "musl_missing.h"
 
 static void manager_free(Manager *m);
-static int  manager_parse_config_file(Manager *m);
-
-static Manager *manager_new(void) {
-#ifdef ENABLE_DEBUG_ELOGIND
-        int dbg_cnt;
-#endif // ENABLE_DEBUG_ELOGIND
-        Manager *m;
-        int r;
-
-        m = new0(Manager, 1);
-        if (!m)
-                return NULL;
-
-        m->pin_cgroupfs_fd = -1;
-
-        m->console_active_fd = -1;
 
+static void manager_reset_config(Manager *m) {
 #if 0 /// elogind does not support autospawning of vts
-        m->reserve_vt_fd = -1;
-
         m->n_autovts = 6;
         m->reserve_vt = 6;
 #endif // 0
@@ -76,15 +63,44 @@ static Manager *manager_new(void) {
         m->handle_hibernate_key = HANDLE_HIBERNATE;
         m->handle_lid_switch = HANDLE_SUSPEND;
         m->handle_lid_switch_docked = HANDLE_IGNORE;
+        m->power_key_ignore_inhibited = false;
+        m->suspend_key_ignore_inhibited = false;
+        m->hibernate_key_ignore_inhibited = false;
         m->lid_switch_ignore_inhibited = true;
+
         m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
 
         m->idle_action_usec = 30 * USEC_PER_MINUTE;
         m->idle_action = HANDLE_IGNORE;
-        m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
 
-        m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
-        m->user_tasks_max = UINT64_C(12288);
+        m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
+        m->user_tasks_max = system_tasks_max_scale(33U, 100U); /* 33% */
+        m->sessions_max = 8192;
+        m->inhibitors_max = 8192;
+
+        m->kill_user_processes = KILL_USER_PROCESSES;
+
+        m->kill_only_users = strv_free(m->kill_only_users);
+        m->kill_exclude_users = strv_free(m->kill_exclude_users);
+#if 1 /// elogind needs an Add-On for sleep configuration
+        elogind_manager_reset_config(m);
+#endif // 1
+}
+
+static Manager *manager_new(void) {
+        Manager *m;
+        int r;
+
+        m = new0(Manager, 1);
+        if (!m)
+                return NULL;
+
+        m->console_active_fd = -1;
+#if 0 /// UNNEEDED by elogind
+        m->reserve_vt_fd = -1;
+#endif // 0
+
+        m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
 
         m->devices = hashmap_new(&string_hash_ops);
         m->seats = hashmap_new(&string_hash_ops);
@@ -96,91 +112,14 @@ static Manager *manager_new(void) {
         m->user_units = hashmap_new(&string_hash_ops);
         m->session_units = hashmap_new(&string_hash_ops);
 
-        m->running_as = MANAGER_SYSTEM;
-        m->test_run   = false;
-
         if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
                 goto fail;
 
-        m->kill_exclude_users = strv_new("root", NULL);
-        if (!m->kill_exclude_users)
-                goto fail;
-
-        /* If elogind should be its own controller, mount its cgroup */
-        if (streq(SYSTEMD_CGROUP_CONTROLLER, "name=elogind")) {
-                r = mount_setup(true);
-                if (r < 0)
-                        goto fail;
-        }
-
-        /* Make cgroups */
-        r = manager_setup_cgroup(m);
+#if 1 /// elogind needs some more data
+        r = elogind_manager_new(m);
         if (r < 0)
                 goto fail;
-
-        m->suspend_mode       = NULL;
-        m->suspend_state      = NULL;
-        m->hibernate_mode     = NULL;
-        m->hibernate_state    = NULL;
-        m->hybrid_sleep_mode  = NULL;
-        m->hybrid_sleep_state = NULL;
-
-        manager_parse_config_file(m);
-
-        /* Set default Sleep config if not already set by logind.conf */
-        if (!m->suspend_state) {
-                m->suspend_state = strv_new("mem", "standby", "freeze", NULL);
-                if (!m->suspend_state)
-                        goto fail;
-        }
-        if (!m->hibernate_mode) {
-                m->hibernate_mode = strv_new("platform", "shutdown", NULL);
-                if (!m->hibernate_mode)
-                        goto fail;
-        }
-        if (!m->hibernate_state) {
-                m->hibernate_state = strv_new("disk", NULL);
-                if (!m->hibernate_state)
-                        goto fail;
-        }
-        if (!m->hybrid_sleep_mode) {
-                m->hybrid_sleep_mode = strv_new("suspend", "platform", "shutdown", NULL);
-                if (!m->hybrid_sleep_mode)
-                        goto fail;
-        }
-        if (!m->hybrid_sleep_state) {
-                m->hybrid_sleep_state = strv_new("disk", NULL);
-                if (!m->hybrid_sleep_state)
-                        goto fail;
-        }
-
-#ifdef ENABLE_DEBUG_ELOGIND
-        dbg_cnt = -1;
-        while (m->suspend_mode && m->suspend_mode[++dbg_cnt])
-                log_debug_elogind("suspend_mode[%d] = %s",
-                                  dbg_cnt, m->suspend_mode[dbg_cnt]);
-        dbg_cnt = -1;
-        while (m->suspend_state[++dbg_cnt])
-                log_debug_elogind("suspend_state[%d] = %s",
-                                  dbg_cnt, m->suspend_state[dbg_cnt]);
-        dbg_cnt = -1;
-        while (m->hibernate_mode[++dbg_cnt])
-                log_debug_elogind("hibernate_mode[%d] = %s",
-                                  dbg_cnt, m->hibernate_mode[dbg_cnt]);
-        dbg_cnt = -1;
-        while (m->hibernate_state[++dbg_cnt])
-                log_debug_elogind("hibernate_state[%d] = %s",
-                                  dbg_cnt, m->hibernate_state[dbg_cnt]);
-        dbg_cnt = -1;
-        while (m->hybrid_sleep_mode[++dbg_cnt])
-                log_debug_elogind("hybrid_sleep_mode[%d] = %s",
-                                  dbg_cnt, m->hybrid_sleep_mode[dbg_cnt]);
-        dbg_cnt = -1;
-        while (m->hybrid_sleep_state[++dbg_cnt])
-                log_debug_elogind("hybrid_sleep_state[%d] = %s",
-                                  dbg_cnt, m->hybrid_sleep_state[dbg_cnt]);
-#endif // ENABLE_DEBUG_ELOGIND
-
+#endif // 1
         m->udev = udev_new();
         if (!m->udev)
                 goto fail;
@@ -191,6 +130,8 @@ static Manager *manager_new(void) {
 
         sd_event_set_watchdog(m->event, true);
 
+        manager_reset_config(m);
+
         return m;
 
 fail:
@@ -206,7 +147,8 @@ static void manager_free(Manager *m) {
         Inhibitor *i;
         Button *b;
 
-        assert(m);
+        if (!m)
+                return;
 
         while ((session = hashmap_first(m->sessions)))
                 session_free(session);
@@ -251,12 +193,12 @@ static void manager_free(Manager *m) {
 
         safe_close(m->console_active_fd);
 
-                udev_monitor_unref(m->udev_seat_monitor);
-                udev_monitor_unref(m->udev_device_monitor);
-                udev_monitor_unref(m->udev_vcsa_monitor);
-                udev_monitor_unref(m->udev_button_monitor);
+        udev_monitor_unref(m->udev_seat_monitor);
+        udev_monitor_unref(m->udev_device_monitor);
+        udev_monitor_unref(m->udev_vcsa_monitor);
+        udev_monitor_unref(m->udev_button_monitor);
 
-                udev_unref(m->udev);
+        udev_unref(m->udev);
 
         if (m->unlink_nologin)
                 (void) unlink("/run/nologin");
@@ -269,8 +211,9 @@ static void manager_free(Manager *m) {
 #if 0 /// elogind does not support autospawning of vts
         safe_close(m->reserve_vt_fd);
 #endif // 0
-
-        manager_shutdown_cgroup(m, true);
+#if 1 /// elogind has to free its own data
+        elogind_manager_free(m);
+#endif // 1
 
         strv_free(m->kill_only_users);
         strv_free(m->kill_exclude_users);
@@ -278,14 +221,9 @@ static void manager_free(Manager *m) {
         free(m->scheduled_shutdown_type);
         free(m->scheduled_shutdown_tty);
         free(m->wall_message);
-
-        strv_free(m->suspend_mode);
-        strv_free(m->suspend_state);
-        strv_free(m->hibernate_mode);
-        strv_free(m->hibernate_state);
-        strv_free(m->hybrid_sleep_mode);
-        strv_free(m->hybrid_sleep_state);
-
+#if 0 /// UNNEEDED by elogind
+        free(m->action_job);
+#endif // 0
         free(m);
 }
 
@@ -685,34 +623,6 @@ static int manager_reserve_vt(Manager *m) {
 }
 #endif // 0
 
-static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        Manager *m = userdata;
-        Session *s;
-        const char *cgroup;
-        int r;
-
-        assert(message);
-        assert(m);
-
-        r = sd_bus_message_read(message, "s", &cgroup);
-        if (r < 0) {
-                bus_log_parse_error(r);
-                return 0;
-        }
-
-        s = hashmap_get(m->sessions, cgroup);
-
-        if (!s) {
-                log_warning("Session not found: %s", cgroup);
-                return 0;
-        }
-
-        session_finalize(s);
-        session_free(s);
-
-        return 0;
-}
-
 static int manager_connect_bus(Manager *m) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
@@ -728,14 +638,6 @@ static int manager_connect_bus(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to add manager object vtable: %m");
 
-        /* elogind relies on signals from its release agent */
-        r = sd_bus_add_match(m->bus, NULL,
-                             "type='signal',"
-                             "interface='org.freedesktop.elogind.Agent',"
-                             "member='Released',"
-                             "path='/org/freedesktop/elogind/agent'",
-                             signal_agent_released, m);
-
         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
         if (r < 0)
                 return log_error_errno(r, "Failed to add seat object vtable: %m");
@@ -822,11 +724,18 @@ static int manager_connect_bus(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to register name: %m");
 
-        r = sd_bus_attach_event(m->bus, m->event, 0);
+        r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
         if (r < 0)
                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
 
+#if 0 /// elogind has to setup its release agent
         return 0;
+#else
+        elogind_bus_setup_system(m);
+        r = elogind_setup_cgroups_agent(m);
+
+        return r;
+#endif // 0
 }
 
 static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
@@ -1134,6 +1043,43 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
         return 0;
 }
 
+static int manager_parse_config_file(Manager *m) {
+#if 0 /// elogind parses its own config file
+        assert(m);
+
+        return config_parse_many(PKGSYSCONFDIR "/logind.conf",
+                                 CONF_PATHS_NULSTR("systemd/logind.conf.d"),
+                                 "Login\0",
+                                 config_item_perf_lookup, logind_gperf_lookup,
+                                 false, m);
+#else
+         const char* logind_conf = getenv("ELOGIND_CONF_FILE");
+
+         assert(m);
+
+         if (!logind_conf)
+                 logind_conf = PKGSYSCONFDIR "/logind.conf";
+
+         return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
+                             config_item_perf_lookup, logind_gperf_lookup,
+                             false, false, true, m);
+#endif // 0
+}
+
+static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
+        Manager *m = userdata;
+        int r;
+
+        manager_reset_config(m);
+        r = manager_parse_config_file(m);
+        if (r < 0)
+                log_warning_errno(r, "Failed to parse config file, using defaults: %m");
+        else
+                log_info("Config file reloaded.");
+
+        return 0;
+}
+
 static int manager_startup(Manager *m) {
         int r;
         Seat *seat;
@@ -1145,6 +1091,12 @@ static int manager_startup(Manager *m) {
 
         assert(m);
 
+        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0);
+
+        r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to register SIGHUP handler: %m");
+
         /* Connect to console */
         r = manager_connect_console(m);
         if (r < 0)
@@ -1249,30 +1201,6 @@ static int manager_run(Manager *m) {
         }
 }
 
-static int manager_parse_config_file(Manager *m) {
-#if 0 /// elogind parses its own config file
-
-        assert(m);
-
-        return config_parse_many(PKGSYSCONFDIR "/logind.conf",
-                                 CONF_PATHS_NULSTR("systemd/logind.conf.d"),
-                                 "Login\0",
-                                 config_item_perf_lookup, logind_gperf_lookup,
-                                 false, m);
-#else
-        const char* logind_conf = getenv("ELOGIND_CONF_FILE");
-
-        assert(m);
-
-        if (!logind_conf)
-                logind_conf = PKGSYSCONFDIR "/logind.conf";
-
-        return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
-                            config_item_perf_lookup, logind_gperf_lookup,
-                            false, false, true, m);
-#endif // 0
-}
-
 int main(int argc, char *argv[]) {
         Manager *m = NULL;
         int r;
@@ -1281,12 +1209,15 @@ int main(int argc, char *argv[]) {
         log_set_target(LOG_TARGET_AUTO);
         log_set_facility(LOG_AUTH);
         log_parse_environment();
-        log_open();
 
 #ifdef ENABLE_DEBUG_ELOGIND
         log_set_max_level(LOG_DEBUG);
+        log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
 #endif // ENABLE_DEBUG_ELOGIND
 
+        log_open();
+
+
         umask(0022);
 
         if (argc != 1) {
@@ -1295,7 +1226,7 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        r = mac_selinux_init("/run");
+        r = mac_selinux_init();
         if (r < 0) {
                 log_error_errno(r, "Could not initialize labelling: %m");
                 goto finish;
@@ -1334,6 +1265,8 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        manager_parse_config_file(m);
+
         r = manager_startup(m);
         if (r < 0) {
                 log_error_errno(r, "Failed to fully start up daemon: %m");
@@ -1355,7 +1288,7 @@ finish:
                   "STOPPING=1\n"
                   "STATUS=Shutting down...");
 
-                manager_free(m);
+        manager_free(m);
 
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
similarity index 91%
rename from src/login/logind.conf
rename to src/login/logind.conf.in
index 2c28d34c83c756b86d2cc44365ad37d54ee50f02..27b05fe8a742a9f1e194951a955b88d18665bfbc 100644 (file)
@@ -12,7 +12,7 @@
 # See logind.conf(5) for details.
 
 [Login]
-#KillUserProcesses=no
+#KillUserProcesses=@KILL_USER_PROCESSES@
 #KillOnlyUsers=
 #KillExcludeUsers=root
 #InhibitDelayMaxSec=5
@@ -30,6 +30,9 @@
 #IdleActionSec=30min
 #RuntimeDirectorySize=10%
 #RemoveIPC=yes
+#InhibitorsMax=8192
+#SessionsMax=8192
+#UserTasksMax=33%
 
 [Sleep]
 #SuspendState=mem standby freeze
index 986f98ccc849cc1c18600d6b2daecee5b7ee4bf4..9be29ab280e183f57ed67da3b4083bc27b98cc82 100644 (file)
 
 #include <stdbool.h>
 
+#if 0 /// elogind needs the systems udev header
 #include "libudev.h"
+#else
+#include <libudev.h>
+#endif // 0
 #include "sd-bus.h"
 #include "sd-event.h"
 
-#include "cgroup-util.h"
 #include "hashmap.h"
 #include "list.h"
-#include "path-lookup.h"
 #include "set.h"
 
 typedef struct Manager Manager;
@@ -37,7 +39,14 @@ typedef struct Manager Manager;
 #include "logind-button.h"
 #include "logind-device.h"
 #include "logind-inhibit.h"
-#include "logind-sleep.h"
+
+/// Additional includes needed by elogind
+#include "cgroup-util.h"
+
+#if 1 /// elogind has to ident itself
+#define MANAGER_IS_SYSTEM(m) ((m)->is_system)
+#define MANAGER_IS_USER(m) (!((m)->is_system))
+#endif // 1
 
 struct Manager {
         sd_event *event;
@@ -63,25 +72,31 @@ struct Manager {
         sd_event_source *udev_vcsa_event_source;
         sd_event_source *udev_button_event_source;
 
+#if 0 /// elogind does not support autospawning of vts
+        int console_active_fd;
+
+        unsigned n_autovts;
+
+        unsigned reserve_vt;
+        int reserve_vt_fd;
+#else
         /* Make sure the user cannot accidentally unmount our cgroup
          * file system */
         int pin_cgroupfs_fd;
 
+        /* fd for handling cgroup socket if elogind is its own cgroups manager */
+        int cgroups_agent_fd;
+        sd_event_source *cgroups_agent_event_source;
+
         /* Flags */
-        ManagerRunningAs running_as;
         bool test_run:1;
+        bool is_system:1; /* true if elogind is its own cgroups manager */
 
         /* Data specific to the cgroup subsystem */
         CGroupMask cgroup_supported;
         char *cgroup_root;
 
         int console_active_fd;
-
-#if 0 /// elogind does not support autospawning of vts
-        unsigned n_autovts;
-
-        unsigned reserve_vt;
-        int reserve_vt_fd;
 #endif // 0
 
         Seat *seat0;
@@ -115,8 +130,12 @@ struct Manager {
            contains the action we are supposed to perform after the
            delay is over */
         HandleAction pending_action;
-#endif // 0
 
+        char **suspend_state,      **suspend_mode;
+        char **hibernate_state,    **hibernate_mode;
+        char **hybrid_sleep_state, **hybrid_sleep_mode;
+
+#endif // 0
         sd_event_source *inhibit_timeout_source;
 
         char *scheduled_shutdown_type;
@@ -151,10 +170,6 @@ struct Manager {
 
         bool remove_ipc;
 
-        char **suspend_state,      **suspend_mode;
-        char **hibernate_state,    **hibernate_mode;
-        char **hybrid_sleep_state, **hybrid_sleep_mode;
-
         Hashmap *polkit_registry;
 
         usec_t holdoff_timeout_usec;
@@ -162,6 +177,8 @@ struct Manager {
 
         size_t runtime_dir_size;
         uint64_t user_tasks_max;
+        uint64_t sessions_max;
+        uint64_t inhibitors_max;
 };
 
 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device);
@@ -208,7 +225,7 @@ int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_
 
 #if 0 /// UNNEEDED by elogind
 int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
@@ -223,14 +240,13 @@ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE
 int manager_set_lid_switch_ignore(Manager *m, usec_t until);
 
 int config_parse_tmpfs_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_user_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret);
 
-#if 0 /// UNNEEDED by elogind
 int manager_setup_wall_message_timer(Manager *m);
 bool logind_wall_tty_filter(const char *tty, void *userdata);
-#endif // 0
 
 int manager_dispatch_delayed(Manager *manager, bool timeout);
index 1662d4c428888297d1ba4da5190ccba7abadfb09..b11ab764c02c01a9b89f017fa92d86a26d17ac5c 100644 (file)
@@ -3,9 +3,9 @@
         "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 
 <!--
-  This file is part of systemd.
+  This file is part of elogind.
 
-  systemd is free software; you can redistribute it and/or modify it
+  elogind is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
                        send_interface="org.freedesktop.login1.Session"
                        send_member="SetIdleHint"/>
 
+                <allow send_destination="org.freedesktop.login1"
+                       send_interface="org.freedesktop.login1.Session"
+                       send_member="SetLockedHint"/>
+
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Session"
                        send_member="Kill"/>
index 23326bb79feedf56adae5099e835c86665f92576..caaf1daf2775ee6e06286eea573ab2f95ce24a5e 100644 (file)
@@ -3,9 +3,9 @@
         "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
 
 <!--
-  This file is part of systemd.
+  This file is part of elogind.
 
-  systemd is free software; you can redistribute it and/or modify it
+  elogind is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
@@ -13,8 +13,8 @@
 
 <policyconfig>
 
-        <vendor>The systemd Project</vendor>
-        <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+        <vendor>The elogind Project</vendor>
+        <vendor_url>https://github.com/elogind/elogind</vendor_url>
 
         <action id="org.freedesktop.login1.inhibit-block-shutdown">
                 <_description>Allow applications to inhibit system shutdown</_description>
                 </defaults>
         </action>
 
+        <action id="org.freedesktop.login1.set-self-linger">
+                <_description>Allow non-logged-in user to run programs</_description>
+                <_message>Explicit request is required to run programs as a non-logged-in user.</_message>
+                <defaults>
+                        <allow_any>yes</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
         <action id="org.freedesktop.login1.set-user-linger">
                 <_description>Allow non-logged-in users to run programs</_description>
                 <_message>Authentication is required to run programs as a non-logged-in user.</_message>
index 762dae2bb3a1064d941907b6c3979deb176a1e74..e6eaa00ff0808b6c9ca5744687e9814e175df54a 100644 (file)
@@ -1,6 +1,6 @@
-#  This file is part of systemd.
+#  This file is part of elogind.
 #
-#  systemd is free software; you can redistribute it and/or modify it
+#  elogind is free software; you can redistribute it and/or modify it
 #  under the terms of the GNU Lesser General Public License as published by
 #  the Free Software Foundation; either version 2.1 of the License, or
 #  (at your option) any later version.
index 40e246bb06cd6d07f23ece54816931df0f870e94..4f023640f6517f953a74d4036e27604677b06f2f 100644 (file)
@@ -150,7 +150,7 @@ static int get_seat_from_display(const char *display, const char **seat, uint32_
         if (fd < 0)
                 return -errno;
 
-        if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0)
+        if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
                 return -errno;
 
         r = getpeercred(fd, &ucred);
@@ -182,25 +182,20 @@ static int export_legacy_dbus_address(
         _cleanup_free_ char *s = NULL;
         int r = PAM_BUF_ERR;
 
-        if (is_kdbus_available()) {
-                if (asprintf(&s, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, runtime) < 0)
-                        goto error;
-        } else {
-                /* FIXME: We *really* should move the access() check into the
-                 * daemons that spawn dbus-daemon, instead of forcing
-                 * DBUS_SESSION_BUS_ADDRESS= here. */
+        /* FIXME: We *really* should move the access() check into the
+         * daemons that spawn dbus-daemon, instead of forcing
+         * DBUS_SESSION_BUS_ADDRESS= here. */
 
-                s = strjoin(runtime, "/bus", NULL);
-                if (!s)
-                        goto error;
+        s = strjoin(runtime, "/bus", NULL);
+        if (!s)
+                goto error;
 
-                if (access(s, F_OK) < 0)
-                        return PAM_SUCCESS;
+        if (access(s, F_OK) < 0)
+                return PAM_SUCCESS;
 
-                s = mfree(s);
-                if (asprintf(&s, UNIX_USER_BUS_ADDRESS_FMT, runtime) < 0)
-                        goto error;
-        }
+        s = mfree(s);
+        if (asprintf(&s, UNIX_USER_BUS_ADDRESS_FMT, runtime) < 0)
+                goto error;
 
         r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", s, 0);
         if (r != PAM_SUCCESS)
index bd603e297d29c147250f0f271c0f1be69e645325..cb5bb5e5f7e63374e1caab40f3ff63a2fbacedcd 100644 (file)
 #include <errno.h>
 #include <string.h>
 
+#if 0 /// elogind needs the systems udev header
 #include "libudev.h"
+#else
+#include <libudev.h>
+#endif // 0
 
 #include "alloc-util.h"
 #include "locale-util.h"
@@ -110,7 +114,7 @@ static int show_sysfs_one(
                 if (!k)
                         return -ENOMEM;
 
-                printf("%s%s%s\n", prefix, draw_special_char(lookahead ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT), k);
+                printf("%s%s%s\n", prefix, special_glyph(lookahead ? TREE_BRANCH : TREE_RIGHT), k);
 
                 if (asprintf(&l,
                              "%s%s:%s%s%s%s",
@@ -124,13 +128,13 @@ static int show_sysfs_one(
                 if (!k)
                         return -ENOMEM;
 
-                printf("%s%s%s\n", prefix, lookahead ? draw_special_char(DRAW_TREE_VERTICAL) : "  ", k);
+                printf("%s%s%s\n", prefix, lookahead ? special_glyph(TREE_VERTICAL) : "  ", k);
 
                 *item = next;
                 if (*item) {
                         _cleanup_free_ char *p = NULL;
 
-                        p = strappend(prefix, lookahead ? draw_special_char(DRAW_TREE_VERTICAL) : "  ");
+                        p = strappend(prefix, lookahead ? special_glyph(TREE_VERTICAL) : "  ");
                         if (!p)
                                 return -ENOMEM;
 
@@ -183,7 +187,7 @@ int show_sysfs(const char *seat, const char *prefix, unsigned n_columns) {
         if (first)
                 show_sysfs_one(udev, seat, &first, "/", prefix, n_columns);
         else
-                printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT), "(none)");
+                printf("%s%s%s\n", prefix, special_glyph(TREE_RIGHT), "(none)");
 
         return r;
 }
index 76220d25d47bea2b1e59d38b996ac57b7005f152..47d8bf077a6a25bbdd243411bf283083b0f848c8 100644 (file)
@@ -22,7 +22,6 @@
 
 /// Additional includes needed by elogind
 #include "musl_missing.h"
-
 static void test_session_id_valid(void) {
         assert_se(session_id_valid("c1"));
         assert_se(session_id_valid("1234"));
index a4196bf14b3a6fb8610994be41332059324e9fea..4fbc893a9a0ae7d90cac44945dfa7d0bd4daed67 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "logind-action.h"
 #include "logind-session.h"
-
 #include "test-tables.h"
 
 int main(int argc, char **argv) {
index 2963f9fc4b42fcc2667fb57c3fd82144ffd604e8..b99ecbba5bc0f41a62747287c33b75d49d989908 100644 (file)
@@ -163,7 +163,7 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
 
 int acl_search_groups(const char *path, char ***ret_groups) {
         _cleanup_strv_free_ char **g = NULL;
-        _cleanup_(acl_free) acl_t acl = NULL;
+        _cleanup_(acl_freep) acl_t acl = NULL;
         bool ret = false;
         acl_entry_t entry;
         int r;
index 5fa39ce8c694a5292ef275260bbda176ce94d6e0..5ea4e56087d3fd01b6310652a80dff2379db21d8 100644 (file)
 #include "bus-label.h"
 #include "bus-message.h"
 #include "bus-util.h"
-#include "cgroup-util.h"
 #include "def.h"
-//#include "env-util.h"
 #include "escape.h"
-#include "extract-word.h"
 #include "fd-util.h"
-#include "hashmap.h"
-//#include "install.h"
-#include "kdbus.h"
-#include "log.h"
-#include "macro.h"
 #include "missing.h"
 #include "parse-util.h"
-#include "path-util.h"
 #include "proc-cmdline.h"
-#include "process-util.h"
 //#include "rlimit-util.h"
-#include "set.h"
-#include "signal-util.h"
 #include "stdio-util.h"
-#include "string-util.h"
 #include "strv.h"
-#include "syslog-util.h"
-#include "time-util.h"
-#include "unit-name.h"
 #include "user-util.h"
-#include "utf8.h"
-#include "util.h"
 
 #if 0 /// UNNEEDED by elogind
 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
@@ -716,7 +698,15 @@ int bus_connect_user_systemd(sd_bus **_bus) {
 }
 #endif // 0
 
-int bus_print_property(const char *name, sd_bus_message *property, bool all) {
+#define print_property(name, fmt, ...)                                  \
+        do {                                                            \
+                if (value)                                              \
+                        printf(fmt "\n", __VA_ARGS__);                  \
+                else                                                    \
+                        printf("%s=" fmt "\n", name, __VA_ARGS__);      \
+        } while(0)
+
+int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all) {
         char type;
         const char *contents;
         int r;
@@ -744,7 +734,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                         if (!escaped)
                                 return -ENOMEM;
 
-                        printf("%s=%s\n", name, escaped);
+                        print_property(name, "%s", escaped);
                 }
 
                 return 1;
@@ -757,7 +747,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                 if (r < 0)
                         return r;
 
-                printf("%s=%s\n", name, yes_no(b));
+                print_property(name, "%s", yes_no(b));
 
                 return 1;
         }
@@ -777,14 +767,14 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
 
                         t = format_timestamp(timestamp, sizeof(timestamp), u);
                         if (t || all)
-                                printf("%s=%s\n", name, strempty(t));
+                                print_property(name, "%s", strempty(t));
 
                 } else if (strstr(name, "USec")) {
                         char timespan[FORMAT_TIMESPAN_MAX];
 
-                        printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
+                        print_property(name, "%s", format_timespan(timespan, sizeof(timespan), u, 0));
                 } else
-                        printf("%s=%llu\n", name, (unsigned long long) u);
+                        print_property(name, "%"PRIu64, u);
 
                 return 1;
         }
@@ -796,7 +786,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                 if (r < 0)
                         return r;
 
-                printf("%s=%lld\n", name, (long long) i);
+                print_property(name, "%"PRIi64, i);
 
                 return 1;
         }
@@ -809,9 +799,9 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                         return r;
 
                 if (strstr(name, "UMask") || strstr(name, "Mode"))
-                        printf("%s=%04o\n", name, u);
+                        print_property(name, "%04o", u);
                 else
-                        printf("%s=%u\n", name, (unsigned) u);
+                        print_property(name, "%"PRIu32, u);
 
                 return 1;
         }
@@ -823,7 +813,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                 if (r < 0)
                         return r;
 
-                printf("%s=%i\n", name, (int) i);
+                print_property(name, "%"PRIi32, i);
                 return 1;
         }
 
@@ -834,7 +824,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                 if (r < 0)
                         return r;
 
-                printf("%s=%g\n", name, d);
+                print_property(name, "%g", d);
                 return 1;
         }
 
@@ -847,10 +837,10 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                         if (r < 0)
                                 return r;
 
-                        while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
+                        while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
                                 _cleanup_free_ char *escaped = NULL;
 
-                                if (first)
+                                if (first && !value)
                                         printf("%s=", name);
 
                                 escaped = xescape(str, "\n ");
@@ -864,7 +854,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                         if (r < 0)
                                 return r;
 
-                        if (first && all)
+                        if (first && all && !value)
                                 printf("%s=", name);
                         if (!first || all)
                                 puts("");
@@ -886,7 +876,8 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                         if (all || n > 0) {
                                 unsigned int i;
 
-                                printf("%s=", name);
+                                if (!value)
+                                        printf("%s=", name);
 
                                 for (i = 0; i < n; i++)
                                         printf("%02x", u[i]);
@@ -907,7 +898,8 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
                         if (all || n > 0) {
                                 unsigned int i;
 
-                                printf("%s=", name);
+                                if (!value)
+                                        printf("%s=", name);
 
                                 for (i = 0; i < n; i++)
                                         printf("%08x", u[i]);
@@ -924,7 +916,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
         return 0;
 }
 
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
+int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
@@ -964,7 +956,7 @@ int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, ch
                         if (r < 0)
                                 return r;
 
-                        r = bus_print_property(name, reply, all);
+                        r = bus_print_property(name, reply, value, all);
                         if (r < 0)
                                 return r;
                         if (r == 0) {
@@ -1044,8 +1036,8 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
         }
 
         case SD_BUS_TYPE_ARRAY: {
-               _cleanup_strv_free_ char **l = NULL;
-               char ***p = userdata;
+                _cleanup_strv_free_ char **l = NULL;
+                char ***p = userdata;
 
                 r = bus_message_read_strv_extend(m, &l);
                 if (r < 0)
@@ -1060,7 +1052,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
 
         case SD_BUS_TYPE_BOOLEAN: {
                 unsigned b;
-                bool *p = userdata;
+                int *p = userdata;
 
                 r = sd_bus_message_read_basic(m, type, &b);
                 if (r < 0)
@@ -1072,7 +1064,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
         }
 
         case SD_BUS_TYPE_UINT32: {
-                uint64_t u;
+                uint32_t u;
                 uint32_t *p = userdata;
 
                 r = sd_bus_message_read_basic(m, type, &u);
@@ -1097,6 +1089,19 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
                 break;
         }
 
+        case SD_BUS_TYPE_DOUBLE: {
+                double d;
+                double *p = userdata;
+
+                r = sd_bus_message_read_basic(m, type, &d);
+                if (r < 0)
+                        break;
+
+                *p = d;
+
+                break;
+        }
+
         default:
                 break;
         }
@@ -1384,841 +1389,8 @@ int bus_log_create_error(int r) {
         return log_error_errno(r, "Failed to create bus message: %m");
 }
 
-int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
-        assert(message);
-        assert(u);
-
-        u->machine = NULL;
-
-        return sd_bus_message_read(
-                        message,
-                        "(ssssssouso)",
-                        &u->id,
-                        &u->description,
-                        &u->load_state,
-                        &u->active_state,
-                        &u->sub_state,
-                        &u->following,
-                        &u->unit_path,
-                        &u->job_id,
-                        &u->job_type,
-                        &u->job_path);
-}
-
-int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
-        const char *eq, *field;
-        int r, rl;
-
-        assert(m);
-        assert(assignment);
-
-        eq = strchr(assignment, '=');
-        if (!eq) {
-                log_error("Not an assignment: %s", assignment);
-                return -EINVAL;
-        }
-
-        r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        field = strndupa(assignment, eq - assignment);
-        eq ++;
-
-        if (streq(field, "CPUQuota")) {
-
-                if (isempty(eq))
-                        r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY);
-                else if (endswith(eq, "%")) {
-                        double percent;
-
-                        if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
-                                log_error("CPU quota '%s' invalid.", eq);
-                                return -EINVAL;
-                        }
-
-                        r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) percent * USEC_PER_SEC / 100);
-                } else {
-                        log_error("CPU quota needs to be in percent.");
-                        return -EINVAL;
-                }
-
-                goto finish;
-
-        } else if (streq(field, "EnvironmentFile")) {
-
-                r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1,
-                                          eq[0] == '-' ? eq + 1 : eq,
-                                          eq[0] == '-');
-                goto finish;
-
-        } else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec", "RuntimeMaxSec")) {
-                char *n;
-                usec_t t;
-                size_t l;
-                r = parse_sec(eq, &t);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq);
-
-                l = strlen(field);
-                n = newa(char, l + 2);
-                if (!n)
-                        return log_oom();
-
-                /* Change suffix Sec → USec */
-                strcpy(mempcpy(n, field, l - 3), "USec");
-                r = sd_bus_message_append(m, "sv", n, "t", t);
-                goto finish;
-        }
-
-        r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        rl = rlimit_from_string(field);
-        if (rl >= 0) {
-                const char *sn;
-                struct rlimit l;
-
-                r = rlimit_parse(rl, eq, &l);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to parse resource limit: %s", eq);
-
-                r = sd_bus_message_append(m, "v", "t", l.rlim_max);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                sn = strjoina(field, "Soft");
-                r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur);
-
-        } else if (STR_IN_SET(field,
-                       "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
-                       "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
-                       "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
-                       "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
-                       "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) {
-
-                r = parse_boolean(eq);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment);
-
-                r = sd_bus_message_append(m, "v", "b", r);
-
-        } else if (streq(field, "MemoryLimit")) {
-                uint64_t bytes;
-
-                if (isempty(eq) || streq(eq, "infinity"))
-                        bytes = (uint64_t) -1;
-                else {
-                r = parse_size(eq, 1024, &bytes);
-                if (r < 0) {
-                        log_error("Failed to parse bytes specification %s", assignment);
-                        return -EINVAL;
-                }
-                }
-
-                r = sd_bus_message_append(m, "v", "t", bytes);
-
-        } else if (streq(field, "TasksMax")) {
-                uint64_t n;
-
-                if (isempty(eq) || streq(eq, "infinity"))
-                        n = (uint64_t) -1;
-                else {
-                        r = safe_atou64(eq, &n);
-                        if (r < 0) {
-                                log_error("Failed to parse maximum tasks specification %s", assignment);
-                                return -EINVAL;
-                        }
-                }
-
-                r = sd_bus_message_append(m, "v", "t", n);
-
-        } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
-                uint64_t u;
-
-                r = cg_cpu_shares_parse(eq, &u);
-                if (r < 0) {
-                        log_error("Failed to parse %s value %s.", field, eq);
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "t", u);
-
-        } else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
-                uint64_t u;
-
-                r = cg_cpu_shares_parse(eq, &u);
-                if (r < 0) {
-                        log_error("Failed to parse %s value %s.", field, eq);
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "t", u);
-
-        } else if (STR_IN_SET(field,
-                              "User", "Group", "DevicePolicy", "KillMode",
-                              "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
-                              "StandardInput", "StandardOutput", "StandardError",
-                              "Description", "Slice", "Type", "WorkingDirectory",
-                              "RootDirectory", "SyslogIdentifier", "ProtectSystem",
-                              "ProtectHome"))
-                r = sd_bus_message_append(m, "v", "s", eq);
-
-        else if (streq(field, "SyslogLevel")) {
-                int level;
-
-                level = log_level_from_string(eq);
-                if (level < 0) {
-                        log_error("Failed to parse %s value %s.", field, eq);
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "i", level);
-
-        } else if (streq(field, "SyslogFacility")) {
-                int facility;
-
-                facility = log_facility_unshifted_from_string(eq);
-                if (facility < 0) {
-                        log_error("Failed to parse %s value %s.", field, eq);
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "i", facility);
-
-        } else if (streq(field, "DeviceAllow")) {
-
-                if (isempty(eq))
-                        r = sd_bus_message_append(m, "v", "a(ss)", 0);
-                else {
-                        const char *path, *rwm, *e;
-
-                        e = strchr(eq, ' ');
-                        if (e) {
-                                path = strndupa(eq, e - eq);
-                                rwm = e+1;
-                        } else {
-                                path = eq;
-                                rwm = "";
-                        }
-
-                        if (!path_startswith(path, "/dev")) {
-                                log_error("%s is not a device file in /dev.", path);
-                                return -EINVAL;
-                        }
-
-                        r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
-                }
-
-        } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
-
-                if (isempty(eq))
-                        r = sd_bus_message_append(m, "v", "a(st)", 0);
-                else {
-                        const char *path, *bandwidth, *e;
-                        uint64_t bytes;
-
-                        e = strchr(eq, ' ');
-                        if (e) {
-                                path = strndupa(eq, e - eq);
-                                bandwidth = e+1;
-                        } else {
-                                log_error("Failed to parse %s value %s.", field, eq);
-                                return -EINVAL;
-                        }
-
-                        if (!path_startswith(path, "/dev")) {
-                                log_error("%s is not a device file in /dev.", path);
-                                return -EINVAL;
-                        }
-
-                        r = parse_size(bandwidth, 1000, &bytes);
-                        if (r < 0) {
-                                log_error("Failed to parse byte value %s.", bandwidth);
-                                return -EINVAL;
-                        }
-
-                        r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
-                }
-
-        } else if (streq(field, "BlockIODeviceWeight")) {
-
-                if (isempty(eq))
-                        r = sd_bus_message_append(m, "v", "a(st)", 0);
-                else {
-                        const char *path, *weight, *e;
-                        uint64_t u;
-
-                        e = strchr(eq, ' ');
-                        if (e) {
-                                path = strndupa(eq, e - eq);
-                                weight = e+1;
-                        } else {
-                                log_error("Failed to parse %s value %s.", field, eq);
-                                return -EINVAL;
-                        }
-
-                        if (!path_startswith(path, "/dev")) {
-                                log_error("%s is not a device file in /dev.", path);
-                                return -EINVAL;
-                        }
-
-                        r = safe_atou64(weight, &u);
-                        if (r < 0) {
-                                log_error("Failed to parse %s value %s.", field, weight);
-                                return -EINVAL;
-                        }
-                        r = sd_bus_message_append(m, "v", "a(st)", path, u);
-                }
-
-        } else if (streq(field, "Nice")) {
-                int32_t i;
-
-                r = safe_atoi32(eq, &i);
-                if (r < 0) {
-                        log_error("Failed to parse %s value %s.", field, eq);
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "i", i);
-
-        } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
-                const char *p;
-
-                r = sd_bus_message_open_container(m, 'v', "as");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_open_container(m, 'a', "s");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                p = eq;
-
-                for (;;) {
-                        _cleanup_free_ char *word = NULL;
-
-                        r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
-                        if (r < 0) {
-                                log_error("Failed to parse Environment value %s", eq);
-                                return -EINVAL;
-                        }
-                        if (r == 0)
-                                break;
-
-                        if (streq(field, "Environment")) {
-                                if (!env_assignment_is_valid(word)) {
-                                        log_error("Invalid environment assignment: %s", word);
-                                        return -EINVAL;
-                                }
-                        } else {  /* PassEnvironment */
-                                if (!env_name_is_valid(word)) {
-                                        log_error("Invalid environment variable name: %s", word);
-                                        return -EINVAL;
-                                }
-                        }
-
-                        r = sd_bus_message_append_basic(m, 's', word);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_close_container(m);
-
-        } else if (streq(field, "KillSignal")) {
-                int sig;
-
-                sig = signal_from_string_try_harder(eq);
-                if (sig < 0) {
-                        log_error("Failed to parse %s value %s.", field, eq);
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "i", sig);
-
-        } else if (streq(field, "TimerSlackNSec")) {
-                nsec_t n;
-
-                r = parse_nsec(eq, &n);
-                if (r < 0) {
-                        log_error("Failed to parse %s value %s", field, eq);
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "t", n);
-        } else if (streq(field, "OOMScoreAdjust")) {
-                int oa;
-
-                r = safe_atoi(eq, &oa);
-                if (r < 0) {
-                        log_error("Failed to parse %s value %s", field, eq);
-                        return -EINVAL;
-                }
-
-                if (!oom_score_adjust_is_valid(oa)) {
-                        log_error("OOM score adjust value out of range");
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "i", oa);
-        } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
-                const char *p;
-
-                r = sd_bus_message_open_container(m, 'v', "as");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_open_container(m, 'a', "s");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                p = eq;
-
-                for (;;) {
-                        _cleanup_free_ char *word = NULL;
-                        int offset;
-
-                        r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
-                        if (r < 0) {
-                                log_error("Failed to parse %s value %s", field, eq);
-                                return -EINVAL;
-                        }
-                        if (r == 0)
-                                break;
-
-                        if (!utf8_is_valid(word)) {
-                                log_error("Failed to parse %s value %s", field, eq);
-                                return -EINVAL;
-                        }
-
-                        offset = word[0] == '-';
-                        if (!path_is_absolute(word + offset)) {
-                                log_error("Failed to parse %s value %s", field, eq);
-                                return -EINVAL;
-                        }
-
-                        path_kill_slashes(word + offset);
-
-                        r = sd_bus_message_append_basic(m, 's', word);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_close_container(m);
-
-        } else if (streq(field, "RuntimeDirectory")) {
-                const char *p;
-
-                r = sd_bus_message_open_container(m, 'v', "as");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_open_container(m, 'a', "s");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                p = eq;
-
-                for (;;) {
-                        _cleanup_free_ char *word = NULL;
-
-                        r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to parse %s value %s", field, eq);
-
-                        if (r == 0)
-                                break;
-
-                        r = sd_bus_message_append_basic(m, 's', word);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_close_container(m);
-
-        } else {
-                log_error("Unknown assignment %s.", assignment);
-                return -EINVAL;
-        }
-
-finish:
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_close_container(m);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        return 0;
-}
 #endif // 0
-
-typedef struct BusWaitForJobs {
-        sd_bus *bus;
-        Set *jobs;
-
-        char *name;
-        char *result;
-
-        sd_bus_slot *slot_job_removed;
-        sd_bus_slot *slot_disconnected;
-} BusWaitForJobs;
-
 #if 0 /// UNNEEDED by elogind
-static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
-        assert(m);
-
-        log_error("Warning! D-Bus connection terminated.");
-        sd_bus_close(sd_bus_message_get_bus(m));
-
-        return 0;
-}
-
-static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
-        const char *path, *unit, *result;
-        BusWaitForJobs *d = userdata;
-        uint32_t id;
-        char *found;
-        int r;
-
-        assert(m);
-        assert(d);
-
-        r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
-        if (r < 0) {
-                bus_log_parse_error(r);
-                return 0;
-        }
-
-        found = set_remove(d->jobs, (char*) path);
-        if (!found)
-                return 0;
-
-        free(found);
-
-        if (!isempty(result))
-                d->result = strdup(result);
-
-        if (!isempty(unit))
-                d->name = strdup(unit);
-
-        return 0;
-}
-
-void bus_wait_for_jobs_free(BusWaitForJobs *d) {
-        if (!d)
-                return;
-
-        set_free_free(d->jobs);
-
-        sd_bus_slot_unref(d->slot_disconnected);
-        sd_bus_slot_unref(d->slot_job_removed);
-
-        sd_bus_unref(d->bus);
-
-        free(d->name);
-        free(d->result);
-
-        free(d);
-}
-
-int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
-        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
-        int r;
-
-        assert(bus);
-        assert(ret);
-
-        d = new0(BusWaitForJobs, 1);
-        if (!d)
-                return -ENOMEM;
-
-        d->bus = sd_bus_ref(bus);
-
-        /* When we are a bus client we match by sender. Direct
-         * connections OTOH have no initialized sender field, and
-         * hence we ignore the sender then */
-        r = sd_bus_add_match(
-                        bus,
-                        &d->slot_job_removed,
-                        bus->bus_client ?
-                        "type='signal',"
-                        "sender='org.freedesktop.systemd1',"
-                        "interface='org.freedesktop.systemd1.Manager',"
-                        "member='JobRemoved',"
-                        "path='/org/freedesktop/systemd1'" :
-                        "type='signal',"
-                        "interface='org.freedesktop.systemd1.Manager',"
-                        "member='JobRemoved',"
-                        "path='/org/freedesktop/systemd1'",
-                        match_job_removed, d);
-        if (r < 0)
-                return r;
-
-        r = sd_bus_add_match(
-                        bus,
-                        &d->slot_disconnected,
-                        "type='signal',"
-                        "sender='org.freedesktop.DBus.Local',"
-                        "interface='org.freedesktop.DBus.Local',"
-                        "member='Disconnected'",
-                        match_disconnected, d);
-        if (r < 0)
-                return r;
-
-        *ret = d;
-        d = NULL;
-
-        return 0;
-}
-
-static int bus_process_wait(sd_bus *bus) {
-        int r;
-
-        for (;;) {
-                r = sd_bus_process(bus, NULL);
-                if (r < 0)
-                        return r;
-                if (r > 0)
-                        return 0;
-
-                r = sd_bus_wait(bus, (uint64_t) -1);
-                if (r < 0)
-                        return r;
-        }
-}
-
-static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
-        _cleanup_free_ char *dbus_path = NULL;
-
-        assert(d);
-        assert(d->name);
-        assert(result);
-
-        dbus_path = unit_dbus_path_from_name(d->name);
-        if (!dbus_path)
-                return -ENOMEM;
-
-        return sd_bus_get_property_string(d->bus,
-                                          "org.freedesktop.systemd1",
-                                          dbus_path,
-                                          "org.freedesktop.systemd1.Service",
-                                          "Result",
-                                          NULL,
-                                          result);
-}
-
-static const struct {
-        const char *result, *explanation;
-} explanations [] = {
-        { "resources",   "a configured resource limit was exceeded" },
-        { "timeout",     "a timeout was exceeded" },
-        { "exit-code",   "the control process exited with error code" },
-        { "signal",      "a fatal signal was delivered to the control process" },
-        { "core-dump",   "a fatal signal was delivered causing the control process to dump core" },
-        { "watchdog",    "the service failed to send watchdog ping" },
-        { "start-limit", "start of the service was attempted too often" }
-};
-
-static void log_job_error_with_service_result(const char* service, const char *result, const char *extra_args) {
-        _cleanup_free_ char *service_shell_quoted = NULL, *systemctl_extra_args = NULL;
-
-        assert(service);
-
-        service_shell_quoted = shell_maybe_quote(service);
-
-        systemctl_extra_args = strjoin("systemctl ", extra_args, " ", NULL);
-        if (!systemctl_extra_args) {
-                log_oom();
-                return;
-        }
-
-        systemctl_extra_args = strstrip(systemctl_extra_args);
-
-        if (!isempty(result)) {
-                unsigned i;
-
-                for (i = 0; i < ELEMENTSOF(explanations); ++i)
-                        if (streq(result, explanations[i].result))
-                                break;
-
-                if (i < ELEMENTSOF(explanations)) {
-                        log_error("Job for %s failed because %s. See \"%s status %s\" and \"journalctl -xe\" for details.\n",
-                                  service,
-                                  explanations[i].explanation,
-                                  systemctl_extra_args,
-                                  strna(service_shell_quoted));
-
-                        goto finish;
-                }
-        }
-
-        log_error("Job for %s failed. See \"%s status %s\" and \"journalctl -xe\" for details.\n",
-                  service,
-                  systemctl_extra_args,
-                  strna(service_shell_quoted));
-
-finish:
-        /* For some results maybe additional explanation is required */
-        if (streq_ptr(result, "start-limit"))
-                log_info("To force a start use \"%1$s reset-failed %2$s\" followed by \"%1$s start %2$s\" again.",
-                         systemctl_extra_args,
-                         strna(service_shell_quoted));
-}
-
-static int check_wait_response(BusWaitForJobs *d, bool quiet, const char *extra_args) {
-        int r = 0;
-
-        assert(d->result);
-
-        if (!quiet) {
-                if (streq(d->result, "canceled"))
-                        log_error("Job for %s canceled.", strna(d->name));
-                else if (streq(d->result, "timeout"))
-                        log_error("Job for %s timed out.", strna(d->name));
-                else if (streq(d->result, "dependency"))
-                        log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
-                else if (streq(d->result, "invalid"))
-                        log_error("%s is not active, cannot reload.", strna(d->name));
-                else if (streq(d->result, "assert"))
-                        log_error("Assertion failed on job for %s.", strna(d->name));
-                else if (streq(d->result, "unsupported"))
-                        log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
-                else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
-                        if (d->name) {
-                                int q;
-                                _cleanup_free_ char *result = NULL;
-
-                                q = bus_job_get_service_result(d, &result);
-                                if (q < 0)
-                                        log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
-
-                                log_job_error_with_service_result(d->name, result, extra_args);
-                        } else
-                                log_error("Job failed. See \"journalctl -xe\" for details.");
-                }
-        }
-
-        if (streq(d->result, "canceled"))
-                r = -ECANCELED;
-        else if (streq(d->result, "timeout"))
-                r = -ETIME;
-        else if (streq(d->result, "dependency"))
-                r = -EIO;
-        else if (streq(d->result, "invalid"))
-                r = -ENOEXEC;
-        else if (streq(d->result, "assert"))
-                r = -EPROTO;
-        else if (streq(d->result, "unsupported"))
-                r = -EOPNOTSUPP;
-        else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
-                r = -EIO;
-
-        return r;
-}
-
-int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args) {
-        int r = 0;
-
-        assert(d);
-
-        while (!set_isempty(d->jobs)) {
-                int q;
-
-                q = bus_process_wait(d->bus);
-                if (q < 0)
-                        return log_error_errno(q, "Failed to wait for response: %m");
-
-                if (d->result) {
-                        q = check_wait_response(d, quiet, extra_args);
-                        /* Return the first error as it is most likely to be
-                         * meaningful. */
-                        if (q < 0 && r == 0)
-                                r = q;
-
-                        log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
-                }
-
-                d->name = mfree(d->name);
-                d->result = mfree(d->result);
-        }
-
-        return r;
-}
-
-int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
-        int r;
-
-        assert(d);
-
-        r = set_ensure_allocated(&d->jobs, &string_hash_ops);
-        if (r < 0)
-                return r;
-
-        return set_put_strdup(d->jobs, path);
-}
-
-int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
-        int r;
-
-        r = bus_wait_for_jobs_add(d, path);
-        if (r < 0)
-                return log_oom();
-
-        return bus_wait_for_jobs(d, quiet, NULL);
-}
-
-int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
-        const char *type, *path, *source;
-        int r;
-
-        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
-                if (!quiet) {
-                        if (streq(type, "symlink"))
-                                log_info("Created symlink from %s to %s.", path, source);
-                        else
-                                log_info("Removed symlink %s.", path);
-                }
-
-                r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
-                if (r < 0)
-                        return r;
-        }
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        r = sd_bus_message_exit_container(m);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        return 0;
-}
-
 /**
  * bus_path_encode_unique() - encode unique object path
  * @b: bus connection or NULL
@@ -2347,40 +1519,6 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send
 }
 #endif // 0
 
-bool is_kdbus_wanted(void) {
-        _cleanup_free_ char *value = NULL;
-#ifdef ENABLE_KDBUS
-        const bool configured = true;
-#else
-        const bool configured = false;
-#endif
-
-        int r;
-
-        if (get_proc_cmdline_key("kdbus", NULL) > 0)
-                return true;
-
-        r = get_proc_cmdline_key("kdbus=", &value);
-        if (r <= 0)
-                return configured;
-
-        return parse_boolean(value) == 1;
-}
-
-bool is_kdbus_available(void) {
-        _cleanup_close_ int fd = -1;
-        struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
-
-        if (!is_kdbus_wanted())
-                return false;
-
-        fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
-        if (fd < 0)
-                return false;
-
-        return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
-}
-
 #if 0 /// UNNEEDED by elogind
 int bus_property_get_rlimit(
                 sd_bus *bus,
index e81d3313aecc0ae3ed10b937ec2e3336f0a82336..88c2804d66c81eb33b792c8d40f592beaedba406 100644 (file)
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "sd-bus-vtable.h"
 #include "sd-bus.h"
 #include "sd-event.h"
 
 #include "hashmap.h"
-//#include "install.h"
 #include "macro.h"
 #include "string-util.h"
-#include "time-util.h"
 
 typedef enum BusTransport {
         BUS_TRANSPORT_LOCAL,
@@ -81,17 +78,17 @@ int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *ac
 void bus_verify_polkit_async_registry_free(Hashmap *registry);
 
 #if 0 /// UNNEEDED by elogind
-int bus_open_system_systemd(sd_bus **_bus);
-int bus_open_user_systemd(sd_bus **_bus);
 #endif // 0
+int bus_connect_system_systemd(sd_bus **_bus);
+int bus_connect_user_systemd(sd_bus **_bus);
 
 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus);
 #if 0 /// UNNEEDED by elogind
-bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
 #endif // 0
+int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
 
-int bus_print_property(const char *name, sd_bus_message *property, bool all);
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all);
+int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all);
+int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all);
 
 int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
 
@@ -139,23 +136,7 @@ int bus_log_parse_error(int r);
 int bus_log_create_error(int r);
 
 #if 0 /// UNNEEDED by elogind
-typedef struct UnitInfo {
-        const char *machine;
-        const char *id;
-        const char *description;
-        const char *load_state;
-        const char *active_state;
-        const char *sub_state;
-        const char *following;
-        const char *unit_path;
-        uint32_t job_id;
-        const char *job_type;
-        const char *job_path;
-} UnitInfo;
-
-int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
 #endif // 0
-
 #define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type)              \
         int function(sd_bus *bus,                                       \
                      const char *path,                                  \
@@ -188,27 +169,10 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
         SD_BUS_PROPERTY(name "Monotonic", "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, monotonic), (flags))
 
 #if 0 /// UNNEEDED by elogind
-int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment);
-
-typedef struct BusWaitForJobs BusWaitForJobs;
-
-int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret);
-void bus_wait_for_jobs_free(BusWaitForJobs *d);
-int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path);
-int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args);
-int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free);
-
-int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes);
-
 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path);
 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external);
 #endif // 0
 
-bool is_kdbus_wanted(void);
-bool is_kdbus_available(void);
-
 #if 0 /// UNNEEDED by elogind
 int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
 #endif // 0
index c92ba677e67be0a41480741d8b8b0167747bf7e1..5ba296cc8ca76e462ad68bbdae55f75cb2c26572 100644 (file)
@@ -359,7 +359,6 @@ int clean_ipc(uid_t uid) {
         if (r < 0)
                 ret = r;
 
-
 #if 0 /// elogind does not use mq_open anywhere
         r = clean_posix_mq(uid);
         if (r < 0)
index 66c07a223ec7e2db47ef8100e8e8cf3bf87d40d4..8e6fffe1876addb2b85490761d82513293f0c46f 100644 (file)
@@ -294,7 +294,7 @@ int config_parse(const char *unit,
         _cleanup_free_ char *section = NULL, *continuation = NULL;
         _cleanup_fclose_ FILE *ours = NULL;
         unsigned line = 0, section_line = 0;
-        bool section_ignored = false;
+        bool section_ignored = false, allow_bom = true;
         int r;
 
         assert(filename);
@@ -314,18 +314,22 @@ int config_parse(const char *unit,
 
         fd_warn_permissions(filename, fileno(f));
 
-        while (!feof(f)) {
-                char l[LINE_MAX], *p, *c = NULL, *e;
+        for (;;) {
+                char buf[LINE_MAX], *l, *p, *c = NULL, *e;
                 bool escaped = false;
 
-                if (!fgets(l, sizeof(l), f)) {
+                if (!fgets(buf, sizeof buf, f)) {
                         if (feof(f))
                                 break;
 
-                        log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
-                        return -errno;
+                        return log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
                 }
 
+                l = buf;
+                if (allow_bom && startswith(l, UTF8_BYTE_ORDER_MARK))
+                        l += strlen(UTF8_BYTE_ORDER_MARK);
+                allow_bom = false;
+
                 truncate_nl(l);
 
                 if (continuation) {
@@ -425,15 +429,15 @@ int config_parse_many(const char *conf_file,
 #define DEFINE_PARSER(type, vartype, conv_func)                         \
         int config_parse_##type(                                        \
                         const char *unit,                               \
-                                const char *filename,                   \
-                                unsigned line,                          \
-                                const char *section,                    \
-                                unsigned section_line,                  \
-                                const char *lvalue,                     \
-                                int ltype,                              \
-                                const char *rvalue,                     \
-                                void *data,                             \
-                                void *userdata) {                       \
+                        const char *filename,                           \
+                        unsigned line,                                  \
+                        const char *section,                            \
+                        unsigned section_line,                          \
+                        const char *lvalue,                             \
+                        int ltype,                                      \
+                        const char *rvalue,                             \
+                        void *data,                                     \
+                        void *userdata) {                               \
                                                                         \
                 vartype *i = data;                                      \
                 int r;                                                  \
@@ -708,6 +712,7 @@ int config_parse_strv(const char *unit,
                       void *userdata) {
 
         char ***sv = data;
+        int r;
 
         assert(filename);
         assert(lvalue);
@@ -721,19 +726,20 @@ int config_parse_strv(const char *unit,
                  * we actually fill in a real empty array here rather
                  * than NULL, since some code wants to know if
                  * something was set at all... */
-                empty = strv_new(NULL, NULL);
+                empty = new0(char*, 1);
                 if (!empty)
                         return log_oom();
 
                 strv_free(*sv);
                 *sv = empty;
+
                 return 0;
         }
 
         for (;;) {
                 char *word = NULL;
-                int r;
-                r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES);
+
+                r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES|EXTRACT_RETAIN_ESCAPE);
                 if (r == 0)
                         break;
                 if (r == -ENOMEM)
@@ -877,4 +883,41 @@ int config_parse_personality(
         *personality = p;
         return 0;
 }
+
+int config_parse_ifname(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        char **s = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                *s = mfree(*s);
+                return 0;
+        }
+
+        if (!ifname_valid(rvalue)) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        r = free_and_strdup(s, rvalue);
+        if (r < 0)
+                return log_oom();
+
+        return 0;
+}
 #endif // 0
index 92cab70b806cece00cbc78f0b4fb1b055b87f2b2..627aacb2eb60377284f5f021b8ad6d410b4a108f 100644 (file)
@@ -134,6 +134,7 @@ int config_parse_log_level(const char *unit, const char *filename, unsigned line
 int config_parse_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 #if 0 /// UNNEEDED by elogind
 int config_parse_personality(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_ifname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 #endif // 0
 
 #define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg)                \
@@ -188,7 +189,7 @@ int config_parse_personality(const char *unit, const char *filename, unsigned li
                 assert(data);                                                  \
                                                                                \
                 xs = new0(type, 1);                                            \
-                if(!xs)                                                        \
+                if (!xs)                                                       \
                         return -ENOMEM;                                        \
                                                                                \
                 *xs = invalid;                                                 \
similarity index 90%
rename from src/basic/musl_missing.h
rename to src/shared/musl_missing.h
index 37a7005c90f91f85162d00d85fea24a28f2de4fc..6a6f1e037e78c3646f768650fbe03c617cac1b17 100644 (file)
@@ -85,6 +85,18 @@ typedef int (*__compar_fn_t) (const void *, const void *);
 typedef __compar_fn_t comparison_fn_t;
 #endif
 
+/* Make musl utmp/wtmp stubs visible if needed. */
+#ifdef HAVE_UTMP
+# include <paths.h>
+# include <utmp.h>
+# include <utmpx.h>
+# if defined(_PATH_UTMP) && !defined(_PATH_UTMPX)
+#   define _PATH_UTMPX _PATH_UTMP
+# endif
+# if defined(_PATH_WTMP) && !defined(_PATH_WTMPX)
+#   define _PATH_WTMPX _PATH_WTMP
+# endif
+#endif // HAVE_UTMP
 
 #endif // !defined(__GLIBC__)
 
index 0e21065076e50cf0676fd85b52bf5886220a5928..bb3e17fee2af206041162b7f0297c9cde520a461 100644 (file)
@@ -52,16 +52,19 @@ noreturn static void pager_fallback(void) {
         _exit(EXIT_SUCCESS);
 }
 
-int pager_open(bool jump_to_end) {
+int pager_open(bool no_pager, bool jump_to_end) {
         _cleanup_close_pair_ int fd[2] = { -1, -1 };
         const char *pager;
         pid_t parent_pid;
 
+        if (no_pager)
+                return 0;
+
         if (pager_pid > 0)
                 return 1;
 
-        if (!on_tty())
-                        return 0;
+        if (terminal_is_dumb())
+                return 0;
 
         pager = getenv("SYSTEMD_PAGER");
         if (!pager)
@@ -155,13 +158,13 @@ void pager_close(void) {
                 return;
 
         /* Inform pager that we are done */
-#if defined(__GLIBC__)
+#ifdef __GLIBC__
         stdout = safe_fclose(stdout);
         stderr = safe_fclose(stderr);
 #else
-        (void) safe_fclose(stdout);
-        (void) safe_fclose(stderr);
-#endif // in musl-libc these are const
+        safe_fclose(stdout);
+        safe_fclose(stderr);
+#endif // __GLIBC__
 
         (void) kill(pager_pid, SIGCONT);
         (void) wait_for_terminate(pager_pid, NULL);
index 7e1c91d1aa4a75602cee4145403d659a23425739..2746b1153228587843d877d3d6ec7b4598e70ab4 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "macro.h"
 
-int pager_open(bool jump_to_end);
+int pager_open(bool no_pager, bool jump_to_end);
 void pager_close(void);
 bool pager_have(void) _pure_;
 
diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h
deleted file mode 100644 (file)
index adc7788..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#pragma once
-
-/***
-  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 Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-#include "macro.h"
-
-typedef struct LookupPaths {
-        char **unit_path;
-} LookupPaths;
-
-typedef enum ManagerRunningAs {
-        MANAGER_SYSTEM,
-        MANAGER_USER,
-        _MANAGER_RUNNING_AS_MAX,
-        _MANAGER_RUNNING_AS_INVALID = -1
-} ManagerRunningAs;
-
-#if 0 /// UNNEEDED by elogind
-int user_config_home(char **config_home);
-int user_runtime_dir(char **runtime_dir);
-
-char **generator_paths(ManagerRunningAs running_as);
-
-int lookup_paths_init(LookupPaths *p,
-                      ManagerRunningAs running_as,
-                      bool personal,
-                      const char *root_dir,
-                      const char *generator,
-                      const char *generator_early,
-                      const char *generator_late);
-
-#include "install.h"
-
-int lookup_paths_init_from_scope(LookupPaths *paths,
-                                 UnitFileScope scope,
-                                 const char *root_dir);
-
-void lookup_paths_free(LookupPaths *p);
-#define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free)
-#endif // 0
similarity index 62%
rename from src/login/logind-sleep.c
rename to src/shared/sleep-config.c
index cd6691aced8747b65e8d4f1a13d0e4c98456d863..7d47e79ebf1493c151285b51eb0c28e8c45c4f77 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
+//#include <errno.h>
+//#include <stdbool.h>
+//#include <stddef.h>
+//#include <stdio.h>
+//#include <string.h>
 //#include <syslog.h>
 //#include <unistd.h>
 
-#include "sd-messages.h"
-
-//#include "alloc-util.h"
+#include "alloc-util.h"
 //#include "conf-parser.h"
 //#include "def.h"
+//#include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
-#include "log.h"
-#include "logind-sleep.h"
+//#include "log.h"
 //#include "macro.h"
 #include "parse-util.h"
+#include "sleep-config.h"
 #include "string-util.h"
 #include "strv.h"
 
-static int can_sleep_state(char **types) {
+#if 0 /// UNNEEDED by elogind
+#define USE(x, y) do { (x) = (y); (y) = NULL; } while (0)
+
+int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
+
+        _cleanup_strv_free_ char
+                **suspend_mode = NULL, **suspend_state = NULL,
+                **hibernate_mode = NULL, **hibernate_state = NULL,
+                **hybrid_mode = NULL, **hybrid_state = NULL;
+        char **modes, **states;
+
+        const ConfigTableItem items[] = {
+                { "Sleep",   "SuspendMode",      config_parse_strv,  0, &suspend_mode  },
+                { "Sleep",   "SuspendState",     config_parse_strv,  0, &suspend_state },
+                { "Sleep",   "HibernateMode",    config_parse_strv,  0, &hibernate_mode  },
+                { "Sleep",   "HibernateState",   config_parse_strv,  0, &hibernate_state },
+                { "Sleep",   "HybridSleepMode",  config_parse_strv,  0, &hybrid_mode  },
+                { "Sleep",   "HybridSleepState", config_parse_strv,  0, &hybrid_state },
+                {}
+        };
+
+        config_parse_many(PKGSYSCONFDIR "/sleep.conf",
+                          CONF_PATHS_NULSTR("systemd/sleep.conf.d"),
+                          "Sleep\0", config_item_table_lookup, items,
+                          false, NULL);
+
+        if (streq(verb, "suspend")) {
+                /* empty by default */
+                USE(modes, suspend_mode);
+
+                if (suspend_state)
+                        USE(states, suspend_state);
+                else
+                        states = strv_new("mem", "standby", "freeze", NULL);
+
+        } else if (streq(verb, "hibernate")) {
+                if (hibernate_mode)
+                        USE(modes, hibernate_mode);
+                else
+                        modes = strv_new("platform", "shutdown", NULL);
+
+                if (hibernate_state)
+                        USE(states, hibernate_state);
+                else
+                        states = strv_new("disk", NULL);
+
+        } else if (streq(verb, "hybrid-sleep")) {
+                if (hybrid_mode)
+                        USE(modes, hybrid_mode);
+                else
+                        modes = strv_new("suspend", "platform", "shutdown", NULL);
+
+                if (hybrid_state)
+                        USE(states, hybrid_state);
+                else
+                        states = strv_new("disk", NULL);
+
+        } else
+                assert_not_reached("what verb");
+
+        if ((!modes && !streq(verb, "suspend")) || !states) {
+                strv_free(modes);
+                strv_free(states);
+                return log_oom();
+        }
+
+        *_modes = modes;
+        *_states = states;
+        return 0;
+}
+#endif // 0
+
+#if 1 /// Only available in this file for elogind
+static
+#endif // 0
+int can_sleep_state(char **types) {
         char **type;
         int r;
         _cleanup_free_ char *p = NULL;
@@ -68,7 +142,10 @@ static int can_sleep_state(char **types) {
         return false;
 }
 
-static int can_sleep_disk(char **types) {
+#if 1 /// Only available in this file for elogind
+static
+#endif // 0
+int can_sleep_disk(char **types) {
         char **type;
         int r;
         _cleanup_free_ char *p = NULL;
@@ -163,6 +240,11 @@ static bool enough_memory_for_hibernation(void) {
         size_t size = 0, used = 0;
         int r;
 
+#if 0 /// elogind does not allow any bypass, we are never init!
+        if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0)
+                return true;
+#endif // 0
+
         r = hibernation_partition_size(&size, &used);
         if (r < 0)
                 return false;
@@ -187,6 +269,25 @@ static bool enough_memory_for_hibernation(void) {
         return r;
 }
 
+#if 0 /// elogind has to do, or better, *can* do it differently
+int can_sleep(const char *verb) {
+        _cleanup_strv_free_ char **modes = NULL, **states = NULL;
+        int r;
+
+        assert(streq(verb, "suspend") ||
+               streq(verb, "hibernate") ||
+               streq(verb, "hybrid-sleep"));
+
+        r = parse_sleep_config(verb, &modes, &states);
+        if (r < 0)
+                return false;
+
+        if (!can_sleep_state(states) || !can_sleep_disk(modes))
+                return false;
+
+        return streq(verb, "suspend") || enough_memory_for_hibernation();
+}
+#else
 int can_sleep(Manager *m, const char *verb) {
 
         assert(streq(verb, "suspend") ||
@@ -211,99 +312,4 @@ int can_sleep(Manager *m, const char *verb) {
 
         return streq(verb, "suspend") || enough_memory_for_hibernation();
 }
-
-static int write_mode(char **modes) {
-        int r = 0;
-        char **mode;
-
-        STRV_FOREACH(mode, modes) {
-                int k;
-
-                k = write_string_file("/sys/power/disk", *mode, 0);
-                if (k == 0)
-                        return 0;
-
-                log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m",
-                                *mode);
-                if (r == 0)
-                        r = k;
-        }
-
-        if (r < 0)
-                log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");
-
-        return r;
-}
-
-static int write_state(FILE **f, char **states) {
-        char **state;
-        int r = 0;
-
-        STRV_FOREACH(state, states) {
-                int k;
-
-                k = write_string_stream(*f, *state, true);
-                if (k == 0)
-                        return 0;
-                log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
-                                *state);
-                if (r == 0)
-                        r = k;
-
-                fclose(*f);
-                *f = fopen("/sys/power/state", "we");
-                if (!*f)
-                        return log_error_errno(errno, "Failed to open /sys/power/state: %m");
-        }
-
-        return r;
-}
-
-int do_sleep(const char *arg_verb, char **modes, char **states) {
-
-        char *arguments[] = {
-                NULL,
-                (char*) "pre",
-                (char*) arg_verb,
-                NULL
-        };
-        static const char* const dirs[] = {SYSTEM_SLEEP_PATH, NULL};
-
-        int r;
-        _cleanup_fclose_ FILE *f = NULL;
-
-        /* This file is opened first, so that if we hit an error,
-         * we can abort before modifying any state. */
-        f = fopen("/sys/power/state", "we");
-        if (!f)
-                return log_error_errno(errno, "Failed to open /sys/power/state: %m");
-
-        /* Configure the hibernation mode */
-        r = write_mode(modes);
-        if (r < 0)
-                return r;
-
-        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
-
-        log_struct(LOG_INFO,
-                   LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START),
-                   LOG_MESSAGE("Suspending system..."),
-                   "SLEEP=%s", arg_verb,
-                   NULL);
-
-        r = write_state(&f, states);
-        if (r < 0)
-                return r;
-
-        log_struct(LOG_INFO,
-                   LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
-                   LOG_MESSAGE("System resumed."),
-                   "SLEEP=%s", arg_verb,
-                   NULL);
-
-        arguments[1] = (char*) "post";
-        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
-
-        return r;
-}
-
+#endif // 0
similarity index 72%
rename from src/login/logind-sleep.h
rename to src/shared/sleep-config.h
index c493c68ddd26c8e05150a10ac463a8e5b31af56c..238775dc4c0333dd94de951587222d0a57198240 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "logind.h"
+#if 0 /// UNNEEDED by elogind
+int parse_sleep_config(const char *verb, char ***modes, char ***states);
 
-int can_sleep(Manager *m, const char *verb);
-int do_sleep(const char *arg_verb, char **modes, char **states);
+int can_sleep(const char *verb);
+int can_sleep_disk(char **types);
+int can_sleep_state(char **types);
+#else
+#include <logind.h>
+int can_sleep(Manager* m, const char *verb);
+#endif // 0
index cf3c8ad5a346680961a80a895d5d244a932bf4f0..7dae4d14fe22648a64fcfb3f3ef2fdd84cc0b135 100644 (file)
@@ -44,6 +44,10 @@ int polkit_agent_open(void) {
         if (agent_pid > 0)
                 return 0;
 
+        /* Clients that run as root don't need to activate/query polkit */
+        if (geteuid() == 0)
+                return 0;
+
         /* We check STDIN here, not STDOUT, since this is about input,
          * not output */
         if (!isatty(STDIN_FILENO))
index 74fe57e6d0fba1c5569be3f2dc61f9f8497fe3d8..d76ff52863e7805e174eb74026eb731a0fd3e3e4 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#if 0 /// elogind needs the systems udev header
+#include "udev.h"
+#else
 #include <libudev.h>
+#endif // 0
 #include "util.h"
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref);
diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c
new file mode 100644 (file)
index 0000000..9750dcd
--- /dev/null
@@ -0,0 +1,445 @@
+/***
+  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 Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <utmpx.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "hostname-util.h"
+#include "macro.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "terminal-util.h"
+#include "time-util.h"
+#include "user-util.h"
+#include "util.h"
+#include "utmp-wtmp.h"
+
+int utmp_get_runlevel(int *runlevel, int *previous) {
+        struct utmpx *found, lookup = { .ut_type = RUN_LVL };
+        int r;
+        const char *e;
+
+        assert(runlevel);
+
+        /* If these values are set in the environment this takes
+         * precedence. Presumably, sysvinit does this to work around a
+         * race condition that would otherwise exist where we'd always
+         * go to disk and hence might read runlevel data that might be
+         * very new and does not apply to the current script being
+         * executed. */
+
+        e = getenv("RUNLEVEL");
+        if (e && e[0] > 0) {
+                *runlevel = e[0];
+
+                if (previous) {
+                        /* $PREVLEVEL seems to be an Upstart thing */
+
+                        e = getenv("PREVLEVEL");
+                        if (e && e[0] > 0)
+                                *previous = e[0];
+                        else
+                                *previous = 0;
+                }
+
+                return 0;
+        }
+
+        if (utmpxname(_PATH_UTMPX) < 0)
+                return -errno;
+
+        setutxent();
+
+        found = getutxid(&lookup);
+        if (!found)
+                r = -errno;
+        else {
+                int a, b;
+
+                a = found->ut_pid & 0xFF;
+                b = (found->ut_pid >> 8) & 0xFF;
+
+                *runlevel = a;
+                if (previous)
+                        *previous = b;
+
+                r = 0;
+        }
+
+        endutxent();
+
+        return r;
+}
+
+static void init_timestamp(struct utmpx *store, usec_t t) {
+        assert(store);
+
+        if (t <= 0)
+                t = now(CLOCK_REALTIME);
+
+        store->ut_tv.tv_sec = t / USEC_PER_SEC;
+        store->ut_tv.tv_usec = t % USEC_PER_SEC;
+}
+
+static void init_entry(struct utmpx *store, usec_t t) {
+        struct utsname uts = {};
+
+        assert(store);
+
+        init_timestamp(store, t);
+
+        if (uname(&uts) >= 0)
+                strncpy(store->ut_host, uts.release, sizeof(store->ut_host));
+
+        strncpy(store->ut_line, "~", sizeof(store->ut_line));  /* or ~~ ? */
+        strncpy(store->ut_id, "~~", sizeof(store->ut_id));
+}
+
+static int write_entry_utmp(const struct utmpx *store) {
+        int r;
+
+        assert(store);
+
+        /* utmp is similar to wtmp, but there is only one entry for
+         * each entry type resp. user; i.e. basically a key/value
+         * table. */
+
+        if (utmpxname(_PATH_UTMPX) < 0)
+                return -errno;
+
+        setutxent();
+
+        if (!pututxline(store))
+                r = -errno;
+        else
+                r = 0;
+
+        endutxent();
+
+        return r;
+}
+
+static int write_entry_wtmp(const struct utmpx *store) {
+        assert(store);
+
+        /* wtmp is a simple append-only file where each entry is
+        simply appended to the end; i.e. basically a log. */
+
+        errno = 0;
+        updwtmpx(_PATH_WTMPX, store);
+        return -errno;
+}
+
+static int write_utmp_wtmp(const struct utmpx *store_utmp, const struct utmpx *store_wtmp) {
+        int r, s;
+
+        r = write_entry_utmp(store_utmp);
+        s = write_entry_wtmp(store_wtmp);
+
+        if (r >= 0)
+                r = s;
+
+        /* If utmp/wtmp have been disabled, that's a good thing, hence
+         * ignore the errors */
+        if (r == -ENOENT)
+                r = 0;
+
+        return r;
+}
+
+static int write_entry_both(const struct utmpx *store) {
+        return write_utmp_wtmp(store, store);
+}
+
+int utmp_put_shutdown(void) {
+        struct utmpx store = {};
+
+        init_entry(&store, 0);
+
+        store.ut_type = RUN_LVL;
+        strncpy(store.ut_user, "shutdown", sizeof(store.ut_user));
+
+        return write_entry_both(&store);
+}
+
+int utmp_put_reboot(usec_t t) {
+        struct utmpx store = {};
+
+        init_entry(&store, t);
+
+        store.ut_type = BOOT_TIME;
+        strncpy(store.ut_user, "reboot", sizeof(store.ut_user));
+
+        return write_entry_both(&store);
+}
+
+_pure_ static const char *sanitize_id(const char *id) {
+        size_t l;
+
+        assert(id);
+        l = strlen(id);
+
+        if (l <= sizeof(((struct utmpx*) NULL)->ut_id))
+                return id;
+
+        return id + l - sizeof(((struct utmpx*) NULL)->ut_id);
+}
+
+int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) {
+        struct utmpx store = {
+                .ut_type = INIT_PROCESS,
+                .ut_pid = pid,
+                .ut_session = sid,
+        };
+        int r;
+
+        assert(id);
+
+        init_timestamp(&store, 0);
+
+        /* ut_id needs only be nul-terminated if it is shorter than sizeof(ut_id) */
+        strncpy(store.ut_id, sanitize_id(id), sizeof(store.ut_id));
+
+        if (line)
+                strncpy(store.ut_line, basename(line), sizeof(store.ut_line));
+
+        r = write_entry_both(&store);
+        if (r < 0)
+                return r;
+
+        if (ut_type == LOGIN_PROCESS || ut_type == USER_PROCESS) {
+                store.ut_type = LOGIN_PROCESS;
+                r = write_entry_both(&store);
+                if (r < 0)
+                        return r;
+        }
+
+        if (ut_type == USER_PROCESS) {
+                store.ut_type = USER_PROCESS;
+                strncpy(store.ut_user, user, sizeof(store.ut_user)-1);
+                r = write_entry_both(&store);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
+        struct utmpx lookup = {
+                .ut_type = INIT_PROCESS /* looks for DEAD_PROCESS, LOGIN_PROCESS, USER_PROCESS, too */
+        }, store, store_wtmp, *found;
+
+        assert(id);
+
+        setutxent();
+
+        /* ut_id needs only be nul-terminated if it is shorter than sizeof(ut_id) */
+        strncpy(lookup.ut_id, sanitize_id(id), sizeof(lookup.ut_id));
+
+        found = getutxid(&lookup);
+        if (!found)
+                return 0;
+
+        if (found->ut_pid != pid)
+                return 0;
+
+        memcpy(&store, found, sizeof(store));
+        store.ut_type = DEAD_PROCESS;
+        store.ut_exit.e_termination = code;
+        store.ut_exit.e_exit = status;
+
+        zero(store.ut_user);
+        zero(store.ut_host);
+        zero(store.ut_tv);
+
+        memcpy(&store_wtmp, &store, sizeof(store_wtmp));
+        /* wtmp wants the current time */
+        init_timestamp(&store_wtmp, 0);
+
+        return write_utmp_wtmp(&store, &store_wtmp);
+}
+
+
+int utmp_put_runlevel(int runlevel, int previous) {
+        struct utmpx store = {};
+        int r;
+
+        assert(runlevel > 0);
+
+        if (previous <= 0) {
+                /* Find the old runlevel automatically */
+
+                r = utmp_get_runlevel(&previous, NULL);
+                if (r < 0) {
+                        if (r != -ESRCH)
+                                return r;
+
+                        previous = 0;
+                }
+        }
+
+        if (previous == runlevel)
+                return 0;
+
+        init_entry(&store, 0);
+
+        store.ut_type = RUN_LVL;
+        store.ut_pid = (runlevel & 0xFF) | ((previous & 0xFF) << 8);
+        strncpy(store.ut_user, "runlevel", sizeof(store.ut_user));
+
+        return write_entry_both(&store);
+}
+
+#define TIMEOUT_MSEC 50
+
+static int write_to_terminal(const char *tty, const char *message) {
+        _cleanup_close_ int fd = -1;
+        const char *p;
+        size_t left;
+        usec_t end;
+
+        assert(tty);
+        assert(message);
+
+        fd = open(tty, O_WRONLY|O_NDELAY|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0 || !isatty(fd))
+                return -errno;
+
+        p = message;
+        left = strlen(message);
+
+        end = now(CLOCK_MONOTONIC) + TIMEOUT_MSEC*USEC_PER_MSEC;
+
+        while (left > 0) {
+                ssize_t n;
+                struct pollfd pollfd = {
+                        .fd = fd,
+                        .events = POLLOUT,
+                };
+                usec_t t;
+                int k;
+
+                t = now(CLOCK_MONOTONIC);
+
+                if (t >= end)
+                        return -ETIME;
+
+                k = poll(&pollfd, 1, (end - t) / USEC_PER_MSEC);
+                if (k < 0)
+                        return -errno;
+
+                if (k == 0)
+                        return -ETIME;
+
+                n = write(fd, p, left);
+                if (n < 0) {
+                        if (errno == EAGAIN)
+                                continue;
+
+                        return -errno;
+                }
+
+                assert((size_t) n <= left);
+
+                p += n;
+                left -= n;
+        }
+
+        return 0;
+}
+
+int utmp_wall(
+        const char *message,
+        const char *username,
+        const char *origin_tty,
+        bool (*match_tty)(const char *tty, void *userdata),
+        void *userdata) {
+
+        _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *stdin_tty = NULL;
+        char date[FORMAT_TIMESTAMP_MAX];
+        struct utmpx *u;
+        int r;
+
+        hn = gethostname_malloc();
+        if (!hn)
+                return -ENOMEM;
+        if (!username) {
+                un = getlogname_malloc();
+                if (!un)
+                        return -ENOMEM;
+        }
+
+        if (!origin_tty) {
+                getttyname_harder(STDIN_FILENO, &stdin_tty);
+                origin_tty = stdin_tty;
+        }
+
+        if (asprintf(&text,
+                     "\a\r\n"
+                     "Broadcast message from %s@%s%s%s (%s):\r\n\r\n"
+                     "%s\r\n\r\n",
+                     un ?: username, hn,
+                     origin_tty ? " on " : "", strempty(origin_tty),
+                     format_timestamp(date, sizeof(date), now(CLOCK_REALTIME)),
+                     message) < 0)
+                return -ENOMEM;
+
+        setutxent();
+
+        r = 0;
+
+        while ((u = getutxent())) {
+                _cleanup_free_ char *buf = NULL;
+                const char *path;
+                int q;
+
+                if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0)
+                        continue;
+
+                /* this access is fine, because strlen("/dev/") << 32 (UT_LINESIZE) */
+                if (path_startswith(u->ut_line, "/dev/"))
+                        path = u->ut_line;
+                else {
+                        if (asprintf(&buf, "/dev/%.*s", (int) sizeof(u->ut_line), u->ut_line) < 0)
+                                return -ENOMEM;
+
+                        path = buf;
+                }
+
+                if (!match_tty || match_tty(path, userdata)) {
+                        q = write_to_terminal(path, text);
+                        if (q < 0)
+                                r = q;
+                }
+        }
+
+        return r;
+}
diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h
new file mode 100644 (file)
index 0000000..438e270
--- /dev/null
@@ -0,0 +1,74 @@
+#pragma once
+
+/***
+  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 Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "time-util.h"
+#include "util.h"
+
+#ifdef HAVE_UTMP
+int utmp_get_runlevel(int *runlevel, int *previous);
+
+int utmp_put_shutdown(void);
+int utmp_put_reboot(usec_t timestamp);
+int utmp_put_runlevel(int runlevel, int previous);
+
+int utmp_put_dead_process(const char *id, pid_t pid, int code, int status);
+int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user);
+
+int utmp_wall(
+        const char *message,
+        const char *username,
+        const char *origin_tty,
+        bool (*match_tty)(const char *tty, void *userdata),
+        void *userdata);
+
+#else /* HAVE_UTMP */
+
+static inline int utmp_get_runlevel(int *runlevel, int *previous) {
+        return -ESRCH;
+}
+static inline int utmp_put_shutdown(void) {
+        return 0;
+}
+static inline int utmp_put_reboot(usec_t timestamp) {
+        return 0;
+}
+static inline int utmp_put_runlevel(int runlevel, int previous) {
+        return 0;
+}
+static inline int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
+        return 0;
+}
+static inline int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) {
+        return 0;
+}
+static inline int utmp_wall(
+                const char *message,
+                const char *username,
+                const char *origin_tty,
+                bool (*match_tty)(const char *tty, void *userdata),
+                void *userdata) {
+        return 0;
+}
+
+#endif /* HAVE_UTMP */
diff --git a/src/sleep/Makefile b/src/sleep/Makefile
new file mode 120000 (symlink)
index 0000000..d0b0e8e
--- /dev/null
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
new file mode 100644 (file)
index 0000000..dc1d55d
--- /dev/null
@@ -0,0 +1,226 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2012 Lennart Poettering
+  Copyright 2013 Zbigniew Jędrzejewski-Szmek
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+//#include <errno.h>
+//#include <getopt.h>
+//#include <stdio.h>
+
+#include "sd-messages.h"
+
+#include "def.h"
+#include "fd-util.h"
+#include "fileio.h"
+//#include "log.h"
+//#include "sleep-config.h"
+//#include "string-util.h"
+#include "strv.h"
+//#include "util.h"
+
+/// Additional includes needed by elogind
+#include "sleep.h"
+
+static char* arg_verb = NULL;
+
+static int write_mode(char **modes) {
+        int r = 0;
+        char **mode;
+
+        STRV_FOREACH(mode, modes) {
+                int k;
+
+                k = write_string_file("/sys/power/disk", *mode, 0);
+                if (k == 0)
+                        return 0;
+
+                log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m",
+                                *mode);
+                if (r == 0)
+                        r = k;
+        }
+
+        if (r < 0)
+                log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");
+
+        return r;
+}
+
+static int write_state(FILE **f, char **states) {
+        char **state;
+        int r = 0;
+
+        STRV_FOREACH(state, states) {
+                int k;
+
+                k = write_string_stream(*f, *state, true);
+                if (k == 0)
+                        return 0;
+                log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
+                                *state);
+                if (r == 0)
+                        r = k;
+
+                fclose(*f);
+                *f = fopen("/sys/power/state", "we");
+                if (!*f)
+                        return log_error_errno(errno, "Failed to open /sys/power/state: %m");
+        }
+
+        return r;
+}
+
+static int execute(char **modes, char **states) {
+
+        char *arguments[] = {
+                NULL,
+                (char*) "pre",
+                arg_verb,
+                NULL
+        };
+        static const char* const dirs[] = {SYSTEM_SLEEP_PATH, NULL};
+
+        int r;
+        _cleanup_fclose_ FILE *f = NULL;
+
+        /* This file is opened first, so that if we hit an error,
+         * we can abort before modifying any state. */
+        f = fopen("/sys/power/state", "we");
+        if (!f)
+                return log_error_errno(errno, "Failed to open /sys/power/state: %m");
+
+        /* Configure the hibernation mode */
+        r = write_mode(modes);
+        if (r < 0)
+                return r;
+
+        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
+
+        log_struct(LOG_INFO,
+                   LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START),
+                   LOG_MESSAGE("Suspending system..."),
+                   "SLEEP=%s", arg_verb,
+                   NULL);
+
+        r = write_state(&f, states);
+        if (r < 0)
+                return r;
+
+        log_struct(LOG_INFO,
+                   LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
+                   LOG_MESSAGE("System resumed."),
+                   "SLEEP=%s", arg_verb,
+                   NULL);
+
+        arguments[1] = (char*) "post";
+        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
+
+        return r;
+}
+
+#if 0 /// elogind calls execute() by itself and does not need another binary
+static void help(void) {
+        printf("%s COMMAND\n\n"
+               "Suspend the system, hibernate the system, or both.\n\n"
+               "Commands:\n"
+               "  -h --help            Show this help and exit\n"
+               "  --version            Print version string and exit\n"
+               "  suspend              Suspend the system\n"
+               "  hibernate            Hibernate the system\n"
+               "  hybrid-sleep         Both hibernate and suspend the system\n"
+               , program_invocation_short_name);
+}
+
+static int parse_argv(int argc, char *argv[]) {
+        enum {
+                ARG_VERSION = 0x100,
+        };
+
+        static const struct option options[] = {
+                { "help",         no_argument,       NULL, 'h'           },
+                { "version",      no_argument,       NULL, ARG_VERSION   },
+                {}
+        };
+
+        int c;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+                switch(c) {
+                case 'h':
+                        help();
+                        return 0; /* done */
+
+                case ARG_VERSION:
+                        return version();
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        assert_not_reached("Unhandled option");
+                }
+
+        if (argc - optind != 1) {
+                log_error("Usage: %s COMMAND",
+                          program_invocation_short_name);
+                return -EINVAL;
+        }
+
+        arg_verb = argv[optind];
+
+        if (!streq(arg_verb, "suspend") &&
+            !streq(arg_verb, "hibernate") &&
+            !streq(arg_verb, "hybrid-sleep")) {
+                log_error("Unknown command '%s'.", arg_verb);
+                return -EINVAL;
+        }
+
+        return 1 /* work to do */;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_strv_free_ char **modes = NULL, **states = NULL;
+        int r;
+
+        log_set_target(LOG_TARGET_AUTO);
+        log_parse_environment();
+        log_open();
+
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                goto finish;
+
+        r = parse_sleep_config(arg_verb, &modes, &states);
+        if (r < 0)
+                goto finish;
+
+        r = execute(modes, states);
+
+finish:
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+#else
+int do_sleep(const char *verb, char **modes, char **states) {
+        assert(verb);
+        arg_verb = (char*)verb;
+        return execute(modes, states);
+}
+#endif // 0
diff --git a/src/sleep/sleep.h b/src/sleep/sleep.h
new file mode 100644 (file)
index 0000000..85669fa
--- /dev/null
@@ -0,0 +1,26 @@
+#pragma once
+#ifndef ELOGIND_SRC_SLEEP_SLEEP_H_INCLUDED
+#define ELOGIND_SRC_SLEEP_SLEEP_H_INCLUDED
+
+/***
+  This file is part of elogind.
+
+  Copyright 2017 Sven Eden
+
+  elogind is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  elogind is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+int do_sleep(const char *verb, char **modes, char **states);
+
+#endif // ELOGIND_SRC_SLEEP_SLEEP_H_INCLUDED
index 2d4e1f26e1ebfe92c55fb56af52573f7fd221127..3bb886be75959100f12c32e62f067927bbe070c0 100644 (file)
@@ -74,7 +74,7 @@
 #endif
 
 #define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func)             \
-        static inline void func##p(type **p) {                  \
+        static __inline__ void func##p(type **p) {              \
                 if (*p)                                         \
                         func(*p);                               \
         }                                                       \
index 47b256d5b9f2246ce5141ff9da2654e1f800f943..623cee0c502d89e9376f611c7d5f92ad50845b86 100644 (file)
@@ -59,7 +59,7 @@ enum {
         SD_BUS_TYPE_STRUCT_END       = ')',
         SD_BUS_TYPE_DICT_ENTRY       = 'e', /* not actually used in signatures */
         SD_BUS_TYPE_DICT_ENTRY_BEGIN = '{',
-        SD_BUS_TYPE_DICT_ENTRY_END   = '}',
+        SD_BUS_TYPE_DICT_ENTRY_END   = '}'
 };
 
 /* Well-known errors. Note that this is only a sanitized subset of the
index 6ad6d519796d1d48c38a0db65e85c0c779842706..e8f84eb5455dc25a263a21efcae949eda6a883fa 100644 (file)
@@ -34,7 +34,7 @@ enum {
         _SD_BUS_VTABLE_METHOD            = 'M',
         _SD_BUS_VTABLE_SIGNAL            = 'S',
         _SD_BUS_VTABLE_PROPERTY          = 'P',
-        _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W',
+        _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W'
 };
 
 enum {
index 402c61dae22369b53b1fb7e74f1454f061f5421a..ae5cba51ba65cd07799dc3af9a4473207b615c8b 100644 (file)
@@ -89,13 +89,13 @@ enum {
         SD_BUS_CREDS_WELL_KNOWN_NAMES   = 1ULL << 32,
         SD_BUS_CREDS_DESCRIPTION        = 1ULL << 33,
         SD_BUS_CREDS_AUGMENT            = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */
-        _SD_BUS_CREDS_ALL               = (1ULL << 34) -1,
+        _SD_BUS_CREDS_ALL               = (1ULL << 34) -1
 };
 
 enum {
         SD_BUS_NAME_REPLACE_EXISTING  = 1ULL << 0,
         SD_BUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1,
-        SD_BUS_NAME_QUEUE             = 1ULL << 2,
+        SD_BUS_NAME_QUEUE             = 1ULL << 2
 };
 
 /* Callbacks */
@@ -258,7 +258,6 @@ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority);
 int sd_bus_message_get_expect_reply(sd_bus_message *m);
 int sd_bus_message_get_auto_start(sd_bus_message *m);
 #endif // 0
-
 int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m);
 
 const char *sd_bus_message_get_signature(sd_bus_message *m, int complete);
@@ -338,6 +337,7 @@ int sd_bus_get_name_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_c
 #if 0 /// UNNEEDED by elogind
 int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine);
 #endif // 0
+
 /* Convenience calls */
 
 int sd_bus_call_method(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, ...);
@@ -345,9 +345,7 @@ int sd_bus_call_method(sd_bus *bus, const char *destination, const char *path, c
 int sd_bus_call_method_async(sd_bus *bus, sd_bus_slot **slot, const char *destination, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata, const char *types, ...);
 #endif // 0
 int sd_bus_get_property(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *type);
-#if 0 /// UNNEEDED by elogind
 int sd_bus_get_property_trivial(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char type, void *ret_ptr);
-#endif // 0
 int sd_bus_get_property_string(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char **ret); /* free the result! */
 #if 0 /// UNNEEDED by elogind
 int sd_bus_get_property_strv(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char ***ret); /* free the result! */
index bb7f34e32d2785b9288766fb565ec0fed3b7fd8f..305b4d604afa85665e1423b86ccde4f3c48fa170 100644 (file)
@@ -200,6 +200,11 @@ int sd_is_mq(int fd, const char *path);
                   invocation. This variable is only supported with
                   sd_pid_notify_with_fds().
 
+     WATCHDOG_USEC=...
+                  Reset watchdog_usec value during runtime.
+                  To reset watchdog_usec value, start the service again.
+                  Example: "WATCHDOG_USEC=20000000"
+
   Daemons can choose to send additional variables. However, it is
   recommended to prefix variable names not listed above with X_.
 
index fd32ac85650b9ebae99a39674e2a149e0b921fba..d17c68d51bc47a4d470aef22e79b172e16949b4c 100644 (file)
@@ -55,7 +55,7 @@ enum {
         SD_EVENT_RUNNING,
         SD_EVENT_EXITING,
         SD_EVENT_FINISHED,
-        SD_EVENT_PREPARING,
+        SD_EVENT_PREPARING
 };
 
 enum {
@@ -69,7 +69,18 @@ typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);
 typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
 typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
 typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
+#if 1 /// elogind is musl-libc compatible, which has other guards for siginfo_t
+#if ( defined(__GLIBC__) \
+   && ( defined(__USE_POSIX199309) || defined(__USE_XOPEN_EXTENDED) ) ) \
+ || (!defined(__GLIBC__) \
+   && ( defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+     || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
+     || defined(_BSD_SOURCE) ) )
 typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
+#else
+typedef void* sd_event_child_handler_t;
+#endif
+#endif // 1
 
 int sd_event_default(sd_event **e);
 
@@ -109,7 +120,10 @@ int sd_event_get_exit_code(sd_event *e, int *code);
 int sd_event_set_watchdog(sd_event *e, int b);
 #if 0 /// UNNEEDED by elogind
 int sd_event_get_watchdog(sd_event *e);
+#endif // 0
+int sd_event_get_iteration(sd_event *e, uint64_t *ret);
 
+#if 0 /// UNNEEDED by elogind
 sd_event_source* sd_event_source_ref(sd_event_source *s);
 #endif // 0
 sd_event_source* sd_event_source_unref(sd_event_source *s);
index a3bf5897b81d0cefadfe5c8a288032a53c7e11a7..4dff0b9b811df5d61cea402907a77294aaedb556 100644 (file)
@@ -100,11 +100,11 @@ int sd_id128_get_boot(sd_id128_t *ret);
                 ((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \
                 0 })
 
-_sd_pure_ static inline int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
+_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
         return memcmp(&a, &b, 16) == 0;
 }
 
-_sd_pure_ static inline int sd_id128_is_null(sd_id128_t a) {
+_sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) {
         return a.qwords[0] == 0 && a.qwords[1] == 0;
 }
 
index 3c10ff032fe7cab39b50df3f26eee52f0a3397ad..e3ecbd83789e0b90da2aeb3d7cc729b7b9a781ad 100644 (file)
@@ -108,7 +108,7 @@ int sd_peer_get_slice(int fd, char **slice);
 int sd_peer_get_user_slice(int fd, char **slice);
 
 /* Similar to sd_pid_get_machine_name(), but retrieves data about the
- * peer of a connected AF_UNIX socket */
+ * peer of a connected AF_UNIX socket */
 int sd_peer_get_machine_name(int fd, char **machine);
 
 /* Similar to sd_pid_get_cgroup(), but retrieves data about the peer
index 8a72576ec8327ae9d69c38e10dab2985293e646d..3c44d63021bce5ebf69cc12eeca6474d6a328264 100644 (file)
@@ -82,8 +82,6 @@ _SD_BEGIN_DECLARATIONS;
 
 #define SD_MESSAGE_INVALID_CONFIGURATION SD_ID128_MAKE(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01)
 
-#define SD_MESSAGE_BOOTCHART        SD_ID128_MAKE(9f,26,aa,56,2c,f4,40,c2,b1,6c,77,3d,04,79,b5,18)
-
 #define SD_MESSAGE_DNSSEC_FAILURE   SD_ID128_MAKE(16,75,d7,f1,72,17,40,98,b1,10,8b,f8,c7,dc,8f,5d)
 #define SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED SD_ID128_MAKE(4d,44,08,cf,d0,d1,44,85,91,84,d1,e6,5d,7c,8a,65)
 #define SD_MESSAGE_DNSSEC_DOWNGRADE SD_ID128_MAKE(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57)
diff --git a/src/update-utmp/Makefile b/src/update-utmp/Makefile
new file mode 120000 (symlink)
index 0000000..d0b0e8e
--- /dev/null
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
new file mode 100644 (file)
index 0000000..9f02172
--- /dev/null
@@ -0,0 +1,315 @@
+/***
+  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 Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_AUDIT
+#include <libaudit.h>
+#endif
+
+#include "sd-bus.h"
+
+//#include "alloc-util.h"
+#include "bus-error.h"
+//#include "bus-util.h"
+//#include "formats-util.h"
+//#include "log.h"
+//#include "macro.h"
+//#include "special.h"
+//#include "unit-name.h"
+//#include "util.h"
+#include "utmp-wtmp.h"
+
+/// Additional includes needed by elogind
+#include "string-util.h"
+#include "time-util.h"
+#include "update-utmp.h"
+typedef struct Context {
+        sd_bus *bus;
+#ifdef HAVE_AUDIT
+        int audit_fd;
+#endif
+} Context;
+
+#if 0 /// UNNEEDED by elogind
+static usec_t get_startup_time(Context *c) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        usec_t t = 0;
+        int r;
+
+        assert(c);
+
+        r = sd_bus_get_property_trivial(
+                        c->bus,
+                        "org.freedesktop.systemd1",
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "UserspaceTimestamp",
+                        &error,
+                        't', &t);
+        if (r < 0) {
+                log_error_errno(r, "Failed to get timestamp: %s", bus_error_message(&error, r));
+                return 0;
+        }
+
+        return t;
+}
+
+static int get_current_runlevel(Context *c) {
+        static const struct {
+                const int runlevel;
+                const char *special;
+        } table[] = {
+                /* The first target of this list that is active or has
+                 * a job scheduled wins. We prefer runlevels 5 and 3
+                 * here over the others, since these are the main
+                 * runlevels used on Fedora. It might make sense to
+                 * change the order on some distributions. */
+                { '5', SPECIAL_GRAPHICAL_TARGET  },
+                { '3', SPECIAL_MULTI_USER_TARGET },
+                { '1', SPECIAL_RESCUE_TARGET     },
+        };
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        int r;
+        unsigned i;
+
+        assert(c);
+
+        for (i = 0; i < ELEMENTSOF(table); i++) {
+                _cleanup_free_ char *state = NULL, *path = NULL;
+
+                path = unit_dbus_path_from_name(table[i].special);
+                if (!path)
+                        return log_oom();
+
+                r = sd_bus_get_property_string(
+                                c->bus,
+                                "org.freedesktop.systemd1",
+                                path,
+                                "org.freedesktop.systemd1.Unit",
+                                "ActiveState",
+                                &error,
+                                &state);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to get state: %s", bus_error_message(&error, r));
+
+                if (streq(state, "active") || streq(state, "reloading"))
+                        return table[i].runlevel;
+        }
+
+        return 0;
+}
+#endif // 0
+
+static int on_reboot(Context *c) {
+        int r = 0, q;
+        usec_t t;
+
+        assert(c);
+
+        /* We finished start-up, so let's write the utmp
+         * record and send the audit msg */
+
+#ifdef HAVE_AUDIT
+        if (c->audit_fd >= 0)
+                if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 &&
+                    errno != EPERM) {
+                        r = log_error_errno(errno, "Failed to send audit message: %m");
+                }
+#endif
+
+#if 0 /// systemd hasn't started the system, so elogind always uses NOW()
+        /* If this call fails it will return 0, which
+         * utmp_put_reboot() will then fix to the current time */
+        t = get_startup_time(c);
+#else
+        t = now(CLOCK_REALTIME);
+#endif // 0
+
+        q = utmp_put_reboot(t);
+        if (q < 0) {
+                log_error_errno(q, "Failed to write utmp record: %m");
+                r = q;
+        }
+
+        return r;
+}
+
+static int on_shutdown(Context *c) {
+        int r = 0, q;
+
+        assert(c);
+
+        /* We started shut-down, so let's write the utmp
+         * record and send the audit msg */
+
+#ifdef HAVE_AUDIT
+        if (c->audit_fd >= 0)
+                if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 &&
+                    errno != EPERM) {
+                        r = log_error_errno(errno, "Failed to send audit message: %m");
+                }
+#endif
+
+        q = utmp_put_shutdown();
+        if (q < 0) {
+                log_error_errno(q, "Failed to write utmp record: %m");
+                r = q;
+        }
+
+        return r;
+}
+
+#if 0 /// UNNEEDED by elogind
+static int on_runlevel(Context *c) {
+        int r = 0, q, previous, runlevel;
+
+        assert(c);
+
+        /* We finished changing runlevel, so let's write the
+         * utmp record and send the audit msg */
+
+        /* First, get last runlevel */
+        q = utmp_get_runlevel(&previous, NULL);
+
+        if (q < 0) {
+                if (q != -ESRCH && q != -ENOENT)
+                        return log_error_errno(q, "Failed to get current runlevel: %m");
+
+                previous = 0;
+        }
+
+        /* Secondly, get new runlevel */
+        runlevel = get_current_runlevel(c);
+
+        if (runlevel < 0)
+                return runlevel;
+
+        if (previous == runlevel)
+                return 0;
+
+#ifdef HAVE_AUDIT
+        if (c->audit_fd >= 0) {
+                _cleanup_free_ char *s = NULL;
+
+                if (asprintf(&s, "old-level=%c new-level=%c",
+                             previous > 0 ? previous : 'N',
+                             runlevel > 0 ? runlevel : 'N') < 0)
+                        return log_oom();
+
+                if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM)
+                        r = log_error_errno(errno, "Failed to send audit message: %m");
+        }
+#endif
+
+        q = utmp_put_runlevel(runlevel, previous);
+        if (q < 0 && q != -ESRCH && q != -ENOENT) {
+                log_error_errno(q, "Failed to write utmp record: %m");
+                r = q;
+        }
+
+        return r;
+}
+#endif // 0
+
+#if 0 /// elogind needs this to be a callable function
+int main(int argc, char *argv[]) {
+#else
+void update_utmp(int argc, char* argv[], sd_bus *bus) {
+#endif // 0
+        Context c = {
+#ifdef HAVE_AUDIT
+                .audit_fd = -1
+#endif
+        };
+#if 0 /// UNNEEDED by elogind
+        int r;
+
+        if (getppid() != 1) {
+                log_error("This program should be invoked by init only.");
+                return EXIT_FAILURE;
+        }
+
+        if (argc != 2) {
+                log_error("This program requires one argument.");
+                return EXIT_FAILURE;
+        }
+
+        log_set_target(LOG_TARGET_AUTO);
+        log_parse_environment();
+        log_open();
+
+        umask(0022);
+#else
+        assert(2 == argc);
+        assert(argv[1]);
+        assert(bus);
+#endif // 0
+
+#ifdef HAVE_AUDIT
+        /* If the kernel lacks netlink or audit support,
+         * don't worry about it. */
+        c.audit_fd = audit_open();
+        if (c.audit_fd < 0 && errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
+                log_error_errno(errno, "Failed to connect to audit log: %m");
+#endif
+#if 0 /// UNNEEDED by elogind
+        r = bus_connect_system_systemd(&c.bus);
+        if (r < 0) {
+                log_error_errno(r, "Failed to get D-Bus connection: %m");
+                r = -EIO;
+                goto finish;
+        }
+
+        log_debug("systemd-update-utmp running as pid "PID_FMT, getpid());
+
+        if (streq(argv[1], "reboot"))
+                r = on_reboot(&c);
+        else if (streq(argv[1], "shutdown"))
+                r = on_shutdown(&c);
+        else if (streq(argv[1], "runlevel"))
+                r = on_runlevel(&c);
+        else {
+                log_error("Unknown command %s", argv[1]);
+                r = -EINVAL;
+        }
+
+        log_debug("systemd-update-utmp stopped as pid "PID_FMT, getpid());
+
+finish:
+#else
+        c.bus = bus;
+        if (streq(argv[1], "reboot"))
+                (void)on_reboot(&c);
+        else if (streq(argv[1], "shutdown"))
+                (void)on_shutdown(&c);
+#endif // 0
+#ifdef HAVE_AUDIT
+        if (c.audit_fd >= 0)
+                audit_close(c.audit_fd);
+#endif
+
+        sd_bus_flush_close_unref(c.bus);
+#if 0 /// UNNEEDED by elogind
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+#endif // 0
+}
diff --git a/src/update-utmp/update-utmp.h b/src/update-utmp/update-utmp.h
new file mode 100644 (file)
index 0000000..7d7d431
--- /dev/null
@@ -0,0 +1,12 @@
+#pragma once
+#ifndef ELOGIND_SRC_UPDATE_UTMP_UPDATE_UTMP_H_INCLUDED
+#define ELOGIND_SRC_UPDATE_UTMP_UPDATE_UTMP_H_INCLUDED
+
+/******************************************************************
+* Make the old main() from update-utmp.c visible as update_utmp() *
+******************************************************************/
+
+void update_utmp(int argc, char* argv[], sd_bus *bus);
+
+
+#endif // ELOGIND_SRC_UPDATE_UTMP_UPDATE_UTMP_H_INCLUDED