chiark / gitweb /
Prep v230: Apply missing upstream fixes and updates (1/8) root build files.
authorSven Eden <yamakuzure@gmx.net>
Tue, 23 May 2017 15:22:48 +0000 (17:22 +0200)
committerSven Eden <yamakuzure@gmx.net>
Fri, 16 Jun 2017 08:12:58 +0000 (10:12 +0200)
.dir-locals.el
.gitignore
.vimrc
CODING_STYLE
Makefile.am
NEWS
TODO
cb/elogind.cbp
configure.ac
src/login/logind.conf.in [moved from src/login/logind.conf with 91% similarity]
src/shared/bus-unit-util.c [deleted file]

index 9d9f8cd..3e1b2d7 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 356388b..68febff 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-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
diff --git a/.vimrc b/.vimrc
index b802c90..284bf88 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 46e3668..b689355 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
index 7facc76..2305caf 100644 (file)
@@ -38,9 +38,9 @@ SUBDIRS = . po
 # Keep the test-suite.log
 .PRECIOUS: $(TEST_SUITE_LOG) Makefile
 
-LIBELOGIND_CURRENT=14
+LIBELOGIND_CURRENT=15
 LIBELOGIND_REVISION=0
-LIBELOGIND_AGE=14
+LIBELOGIND_AGE=15
 
 # Dirs of external packages
 dbuspolicydir=@dbuspolicydir@
@@ -90,6 +90,7 @@ polkitpolicy_files =
 dist_udevrules_DATA =
 nodist_udevrules_DATA =
 dist_pkgsysconf_DATA =
+nodist_pkgsysconf_DATA =
 dist_dbuspolicy_DATA =
 dist_dbussystemservice_DATA =
 check_PROGRAMS =
@@ -128,7 +129,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)\" \
@@ -779,7 +780,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 +802,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 +825,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 +976,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 +984,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
diff --git a/NEWS b/NEWS
index e7f6bb4..7c3f99d 100644 (file)
--- a/NEWS
+++ b/NEWS
 systemd System and Service Manager
 
+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-nspaw@.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.
+
+        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 +314,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 +359,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 +388,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 +451,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:
 
@@ -348,6 +582,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 +652,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:
 
@@ -619,7 +856,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:
 
@@ -739,7 +976,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 +1049,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 +1064,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 +1129,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 +1169,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 +1247,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 +1476,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 +1561,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 +1800,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 +2002,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 +2214,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 +2416,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 +2650,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 +2844,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 +2976,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 +3125,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 +3249,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 +3354,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 +3810,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 +3897,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 +3997,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 +4096,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
diff --git a/TODO b/TODO
index 7437938..fac9ccf 100644 (file)
--- a/TODO
+++ b/TODO
@@ -33,15 +33,55 @@ Janitorial Clean-ups:
 
 Features:
 
+* make sure bash completion uses journalctl --fields to get fields list
+
+* use phyical_memory() to allow MemoryLimit= configuration based on available system memory
+
+* 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
+
+* RestrictNamespaces= or so in services (taking away the ability to create namespaces, with setns, unshare, clone)
+
+* IAID field must move from [Link] to [DHCP] section in .network files
+
+* 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
+
+* 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
+
+* make sure resolved can be restarted without losing pushed-in dns config
+
+* 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: maybe, after all, implement local listening for DNS packets on port
+  127.0.0.53:53.
+
 * 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 +89,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 +99,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.
@@ -80,9 +112,6 @@ Features:
 
 * 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
@@ -112,7 +141,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 +162,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 +173,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?
@@ -233,7 +259,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 +274,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 +304,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 +345,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 +394,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 +514,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
@@ -534,7 +552,6 @@ Features:
 * 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:
@@ -561,8 +578,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 +598,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 +641,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 +755,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 +776,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 c4d879a..6f9ff43 100644 (file)
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/basic/dirent-util.h" />
+               <Unit filename="../src/basic/errno-from-name.h" />
                <Unit filename="../src/basic/errno-list.c">
                        <Option compilerVar="CC" />
                </Unit>
                <Unit filename="../src/basic/errno-list.h" />
+               <Unit filename="../src/basic/errno-to-name.h" />
                <Unit filename="../src/basic/escape.c">
                        <Option compilerVar="CC" />
                </Unit>
                </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/login/logind-device.h" />
+               <Unit filename="../src/login/logind-gperf.c">
+                       <Option compilerVar="CC" />
+               </Unit>
                <Unit filename="../src/login/logind-inhibit.c">
                        <Option compilerVar="CC" />
                </Unit>
index 16cb509..a327e2c 100644 (file)
@@ -20,7 +20,7 @@
 AC_PREREQ([2.64])
 
 AC_INIT([elogind],
-        [229.1],
+        [230],
         [https://github.com/elogind/elogind/issues],
         [elogind],
         [https://github.com/elogind/elogind])
@@ -343,11 +343,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,6 +366,11 @@ 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,
                 IFLA_MACVLAN_FLAGS,
                 IFLA_IPVLAN_MODE,
@@ -368,8 +382,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],
 [], [], [[
@@ -444,6 +459,17 @@ 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]),
                 [case "${enableval}" in
@@ -750,6 +776,7 @@ 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}
similarity index 91%
rename from src/login/logind.conf
rename to src/login/logind.conf.in
index 2c28d34..fc497f2 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=12288
 
 [Sleep]
 #SuspendState=mem standby freeze
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
deleted file mode 100644 (file)
index 68ec4b4..0000000
+++ /dev/null
@@ -1,1302 +0,0 @@
-/***
-  This file is part of elogind.
-
-  Copyright 2016 Lennart Poettering
-
-  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 "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-unit-util.h"
-#include "bus-util.h"
-#include "cgroup-util.h"
-#include "env-util.h"
-#include "escape.h"
-#include "hashmap.h"
-#include "list.h"
-#include "locale-util.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "process-util.h"
-#include "rlimit-util.h"
-#include "signal-util.h"
-#include "string-util.h"
-#include "syslog-util.h"
-#include "terminal-util.h"
-#include "utf8.h"
-#include "util.h"
-
-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", "IOAccounting", "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, "IOWeight", "StartupIOWeight")) {
-                uint64_t u;
-
-                r = cg_weight_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 (cgroup_io_limit_type_from_string(field) >= 0 || 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;
-                        }
-
-                        if (streq(bandwidth, "max")) {
-                                bytes = CGROUP_LIMIT_MAX;
-                        } else {
-                                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 (STR_IN_SET(field, "IODeviceWeight", "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;
-}
-
-typedef struct BusWaitForJobs {
-        sd_bus *bus;
-        Set *jobs;
-
-        char *name;
-        char *result;
-
-        sd_bus_slot *slot_job_removed;
-        sd_bus_slot *slot_disconnected;
-} BusWaitForJobs;
-
-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.elogind1',"
-                        "interface='org.freedesktop.elogind1.Manager',"
-                        "member='JobRemoved',"
-                        "path='/org/freedesktop/elogind1'" :
-                        "type='signal',"
-                        "interface='org.freedesktop.elogind1.Manager',"
-                        "member='JobRemoved',"
-                        "path='/org/freedesktop/elogind1'",
-                        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.elogind1",
-                                          dbus_path,
-                                          "org.freedesktop.elogind1.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* const* extra_args) {
-        _cleanup_free_ char *service_shell_quoted = NULL;
-        const char *systemctl = "systemctl", *journalctl = "journalctl";
-
-        assert(service);
-
-        service_shell_quoted = shell_maybe_quote(service);
-
-        if (extra_args && extra_args[1]) {
-                _cleanup_free_ char *t;
-
-                t = strv_join((char**) extra_args, " ");
-                systemctl = strjoina("systemctl ", t ? : "<args>");
-                journalctl = strjoina("journalctl ", t ? : "<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.\n"
-                                  "See \"%s status %s\" and \"%s -xe\" for details.\n",
-                                  service,
-                                  explanations[i].explanation,
-                                  systemctl,
-                                  service_shell_quoted ?: "<service>",
-                                  journalctl);
-                        goto finish;
-                }
-        }
-
-        log_error("Job for %s failed.\n"
-                  "See \"%s status %s\" and \"%s -xe\" for details.\n",
-                  service,
-                  systemctl,
-                  service_shell_quoted ?: "<service>",
-                  journalctl);
-
-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\"\n"
-                         "followed by \"%1$s start %2$s\" again.",
-                         systemctl,
-                         service_shell_quoted ?: "<service>");
-}
-
-static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* 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* const* 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) {
-                /* We expect only "success" changes to be sent over the bus.
-                   Hence, reject anything negative. */
-                UnitFileChangeType ch = unit_file_change_type_from_string(type);
-
-                if (ch < 0) {
-                        log_notice("Manager reported unknown change type \"%s\" for path \"%s\", ignoring.", type, path);
-                        continue;
-                }
-
-                r = unit_file_changes_add(changes, n_changes, ch, 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);
-
-        unit_file_dump_changes(0, NULL, *changes, *n_changes, false);
-        return 0;
-}
-
-struct CGroupInfo {
-        char *cgroup_path;
-        bool is_const; /* If false, cgroup_path should be free()'d */
-
-        Hashmap *pids; /* PID → process name */
-        bool done;
-
-        struct CGroupInfo *parent;
-        LIST_FIELDS(struct CGroupInfo, siblings);
-        LIST_HEAD(struct CGroupInfo, children);
-        size_t n_children;
-};
-
-static bool IS_ROOT(const char *p) {
-        return isempty(p) || streq(p, "/");
-}
-
-static int add_cgroup(Hashmap *cgroups, const char *path, bool is_const, struct CGroupInfo **ret) {
-        struct CGroupInfo *parent = NULL, *cg;
-        int r;
-
-        assert(cgroups);
-        assert(ret);
-
-        if (IS_ROOT(path))
-                path = "/";
-
-        cg = hashmap_get(cgroups, path);
-        if (cg) {
-                *ret = cg;
-                return 0;
-        }
-
-        if (!IS_ROOT(path)) {
-                const char *e, *pp;
-
-                e = strrchr(path, '/');
-                if (!e)
-                        return -EINVAL;
-
-                pp = strndupa(path, e - path);
-                if (!pp)
-                        return -ENOMEM;
-
-                r = add_cgroup(cgroups, pp, false, &parent);
-                if (r < 0)
-                        return r;
-        }
-
-        cg = new0(struct CGroupInfo, 1);
-        if (!cg)
-                return -ENOMEM;
-
-        if (is_const)
-                cg->cgroup_path = (char*) path;
-        else {
-                cg->cgroup_path = strdup(path);
-                if (!cg->cgroup_path) {
-                        free(cg);
-                        return -ENOMEM;
-                }
-        }
-
-        cg->is_const = is_const;
-        cg->parent = parent;
-
-        r = hashmap_put(cgroups, cg->cgroup_path, cg);
-        if (r < 0) {
-                if (!is_const)
-                        free(cg->cgroup_path);
-                free(cg);
-                return r;
-        }
-
-        if (parent) {
-                LIST_PREPEND(siblings, parent->children, cg);
-                parent->n_children++;
-        }
-
-        *ret = cg;
-        return 1;
-}
-
-static int add_process(
-                Hashmap *cgroups,
-                const char *path,
-                pid_t pid,
-                const char *name) {
-
-        struct CGroupInfo *cg;
-        int r;
-
-        assert(cgroups);
-        assert(name);
-        assert(pid > 0);
-
-        r = add_cgroup(cgroups, path, true, &cg);
-        if (r < 0)
-                return r;
-
-        r = hashmap_ensure_allocated(&cg->pids, &trivial_hash_ops);
-        if (r < 0)
-                return r;
-
-        return hashmap_put(cg->pids, PID_TO_PTR(pid), (void*) name);
-}
-
-static void remove_cgroup(Hashmap *cgroups, struct CGroupInfo *cg) {
-        assert(cgroups);
-        assert(cg);
-
-        while (cg->children)
-                remove_cgroup(cgroups, cg->children);
-
-        hashmap_remove(cgroups, cg->cgroup_path);
-
-        if (!cg->is_const)
-                free(cg->cgroup_path);
-
-        hashmap_free(cg->pids);
-
-        if (cg->parent)
-                LIST_REMOVE(siblings, cg->parent->children, cg);
-
-        free(cg);
-}
-
-static int cgroup_info_compare_func(const void *a, const void *b) {
-        const struct CGroupInfo *x = *(const struct CGroupInfo* const*) a, *y = *(const struct CGroupInfo* const*) b;
-
-        assert(x);
-        assert(y);
-
-        return strcmp(x->cgroup_path, y->cgroup_path);
-}
-
-static int dump_processes(
-                Hashmap *cgroups,
-                const char *cgroup_path,
-                const char *prefix,
-                unsigned n_columns,
-                OutputFlags flags) {
-
-        struct CGroupInfo *cg;
-        int r;
-
-        assert(prefix);
-
-        if (IS_ROOT(cgroup_path))
-                cgroup_path = "/";
-
-        cg = hashmap_get(cgroups, cgroup_path);
-        if (!cg)
-                return 0;
-
-        if (!hashmap_isempty(cg->pids)) {
-                const char *name;
-                size_t n = 0, i;
-                pid_t *pids;
-                void *pidp;
-                Iterator j;
-                int width;
-
-                /* Order processes by their PID */
-                pids = newa(pid_t, hashmap_size(cg->pids));
-
-                HASHMAP_FOREACH_KEY(name, pidp, cg->pids, j)
-                        pids[n++] = PTR_TO_PID(pidp);
-
-                assert(n == hashmap_size(cg->pids));
-                qsort_safe(pids, n, sizeof(pid_t), pid_compare_func);
-
-                width = DECIMAL_STR_WIDTH(pids[n-1]);
-
-                for (i = 0; i < n; i++) {
-                        _cleanup_free_ char *e = NULL;
-                        const char *special;
-                        bool more;
-
-                        name = hashmap_get(cg->pids, PID_TO_PTR(pids[i]));
-                        assert(name);
-
-                        if (n_columns != 0) {
-                                unsigned k;
-
-                                k = MAX(LESS_BY(n_columns, 2U + width + 1U), 20U);
-
-                                e = ellipsize(name, k, 100);
-                                if (e)
-                                        name = e;
-                        }
-
-                        more = i+1 < n || cg->children;
-                        special = special_glyph(more ? TREE_BRANCH : TREE_RIGHT);
-
-                        fprintf(stdout, "%s%s%*"PID_PRI" %s\n",
-                                prefix,
-                                special,
-                                width, pids[i],
-                                name);
-                }
-        }
-
-        if (cg->children) {
-                struct CGroupInfo **children, *child;
-                size_t n = 0, i;
-
-                /* Order subcgroups by their name */
-                children = newa(struct CGroupInfo*, cg->n_children);
-                LIST_FOREACH(siblings, child, cg->children)
-                        children[n++] = child;
-                assert(n == cg->n_children);
-                qsort_safe(children, n, sizeof(struct CGroupInfo*), cgroup_info_compare_func);
-
-                n_columns = MAX(LESS_BY(n_columns, 2U), 20U);
-
-                for (i = 0; i < n; i++) {
-                        _cleanup_free_ char *pp = NULL;
-                        const char *name, *special;
-                        bool more;
-
-                        child = children[i];
-
-                        name = strrchr(child->cgroup_path, '/');
-                        if (!name)
-                                return -EINVAL;
-                        name++;
-
-                        more = i+1 < n;
-                        special = special_glyph(more ? TREE_BRANCH : TREE_RIGHT);
-
-                        fputs(prefix, stdout);
-                        fputs(special, stdout);
-                        fputs(name, stdout);
-                        fputc('\n', stdout);
-
-                        special = special_glyph(more ? TREE_VERTICAL : TREE_SPACE);
-
-                        pp = strappend(prefix, special);
-                        if (!pp)
-                                return -ENOMEM;
-
-                        r = dump_processes(cgroups, child->cgroup_path, pp, n_columns, flags);
-                        if (r < 0)
-                                return r;
-                }
-        }
-
-        cg->done = true;
-        return 0;
-}
-
-static int dump_extra_processes(
-                Hashmap *cgroups,
-                const char *prefix,
-                unsigned n_columns,
-                OutputFlags flags) {
-
-        _cleanup_free_ pid_t *pids = NULL;
-        _cleanup_hashmap_free_ Hashmap *names = NULL;
-        struct CGroupInfo *cg;
-        size_t n_allocated = 0, n = 0, k;
-        Iterator i;
-        int width, r;
-
-        /* Prints the extra processes, i.e. those that are in cgroups we haven't displayed yet. We show them as
-         * combined, sorted, linear list. */
-
-        HASHMAP_FOREACH(cg, cgroups, i) {
-                const char *name;
-                void *pidp;
-                Iterator j;
-
-                if (cg->done)
-                        continue;
-
-                if (hashmap_isempty(cg->pids))
-                        continue;
-
-                r = hashmap_ensure_allocated(&names, &trivial_hash_ops);
-                if (r < 0)
-                        return r;
-
-                if (!GREEDY_REALLOC(pids, n_allocated, n + hashmap_size(cg->pids)))
-                        return -ENOMEM;
-
-                HASHMAP_FOREACH_KEY(name, pidp, cg->pids, j) {
-                        pids[n++] = PTR_TO_PID(pidp);
-
-                        r = hashmap_put(names, pidp, (void*) name);
-                        if (r < 0)
-                                return r;
-                }
-        }
-
-        if (n == 0)
-                return 0;
-
-        qsort_safe(pids, n, sizeof(pid_t), pid_compare_func);
-        width = DECIMAL_STR_WIDTH(pids[n-1]);
-
-        for (k = 0; k < n; k++) {
-                _cleanup_free_ char *e = NULL;
-                const char *name;
-
-                name = hashmap_get(names, PID_TO_PTR(pids[k]));
-                assert(name);
-
-                if (n_columns != 0) {
-                        unsigned z;
-
-                        z = MAX(LESS_BY(n_columns, 2U + width + 1U), 20U);
-
-                        e = ellipsize(name, z, 100);
-                        if (e)
-                                name = e;
-                }
-
-                fprintf(stdout, "%s%s %*" PID_PRI " %s\n",
-                        prefix,
-                        special_glyph(TRIANGULAR_BULLET),
-                        width, pids[k],
-                        name);
-        }
-
-        return 0;
-}
-
-int unit_show_processes(
-                sd_bus *bus,
-                const char *unit,
-                const char *cgroup_path,
-                const char *prefix,
-                unsigned n_columns,
-                OutputFlags flags,
-                sd_bus_error *error) {
-
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        Hashmap *cgroups = NULL;
-        struct CGroupInfo *cg;
-        int r;
-
-        assert(bus);
-        assert(unit);
-
-        if (flags & OUTPUT_FULL_WIDTH)
-                n_columns = 0;
-        else if (n_columns <= 0)
-                n_columns = columns();
-
-        prefix = strempty(prefix);
-
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.elogind1",
-                        "/org/freedesktop/elogind1",
-                        "org.freedesktop.elogind1.Manager",
-                        "GetUnitProcesses",
-                        error,
-                        &reply,
-                        "s",
-                        unit);
-        if (r < 0)
-                return r;
-
-        cgroups = hashmap_new(&string_hash_ops);
-        if (!cgroups)
-                return -ENOMEM;
-
-        r = sd_bus_message_enter_container(reply, 'a', "(sus)");
-        if (r < 0)
-                goto finish;
-
-        for (;;) {
-                const char *path = NULL, *name = NULL;
-                uint32_t pid;
-
-                r = sd_bus_message_read(reply, "(sus)", &path, &pid, &name);
-                if (r < 0)
-                        goto finish;
-                if (r == 0)
-                        break;
-
-                r = add_process(cgroups, path, pid, name);
-                if (r < 0)
-                        goto finish;
-        }
-
-        r = sd_bus_message_exit_container(reply);
-        if (r < 0)
-                goto finish;
-
-        r = dump_processes(cgroups, cgroup_path, prefix, n_columns, flags);
-        if (r < 0)
-                goto finish;
-
-        r = dump_extra_processes(cgroups, prefix, n_columns, flags);
-
-finish:
-        while ((cg = hashmap_first(cgroups)))
-               remove_cgroup(cgroups, cg);
-
-        hashmap_free(cgroups);
-
-        return r;
-}