Merge commit 'v24'

Conflicts:
	units/remote-fs.target.m4
This commit is contained in:
Tollef Fog Heen 2011-04-11 21:10:42 +02:00
commit 015f26d4fd
163 changed files with 4694 additions and 1433 deletions

4
.gitignore vendored
View File

@ -1,3 +1,7 @@
systemd-binfmt
systemd-getty-generator
systemd-nspawn
systemd-stdio-bridge
systemd-machine-id-setup
systemd-detect-virt
systemd-sysctl

View File

@ -30,18 +30,17 @@ bashcompletiondir=$(sysconfdir)/bash_completion.d
# Our own, non-special dirs
pkgsysconfdir=$(sysconfdir)/systemd
userunitdir=$(pkgdatadir)/user
userunitdir=$(prefix)/lib/systemd/user
tmpfilesdir=$(sysconfdir)/tmpfiles.d
usergeneratordir=$(pkglibexecdir)/user-generators
# And these are the special ones for /
rootdir=@rootdir@
rootbindir=$(rootdir)/bin
rootsbindir=$(rootdir)/sbin
rootlibexecdir=$(rootdir)/lib/systemd
systemgeneratordir=$(rootlibexecdir)/system-generators
systemshutdowndir=$(rootlibexecdir)/system-shutdown
systemunitdir=$(rootdir)/lib/systemd/system
systemgeneratordir=$(rootdir)/lib/systemd/system-generators
systemshutdowndir=$(rootdir)/lib/systemd/system-shutdown
AM_CPPFLAGS = \
-include $(top_builddir)/config.h \
@ -58,7 +57,8 @@ AM_CPPFLAGS = \
-DSYSTEMD_SHUTDOWN_BINARY_PATH=\"$(rootlibexecdir)/systemd-shutdown\" \
-DSYSTEMCTL_BINARY_PATH=\"$(rootbindir)/systemctl\" \
-DSYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH=\"$(rootbindir)/systemd-tty-ask-password-agent\" \
-DRUNTIME_DIR=\"$(localstatedir)/run\" \
-DSYSTEMD_STDIO_BRIDGE_BINARY_PATH=\"$(bindir)/systemd-stdio-bridge\" \
-DRUNTIME_DIR=\"/run\" \
-DRANDOM_SEED=\"$(localstatedir)/lib/random-seed\" \
-DSYSTEMD_CRYPTSETUP_PATH=\"$(rootlibexecdir)/systemd-cryptsetup\" \
-DSYSTEM_GENERATOR_PATH=\"$(systemgeneratordir)\" \
@ -109,7 +109,12 @@ rootbin_PROGRAMS = \
systemd-machine-id-setup
bin_PROGRAMS = \
systemd-cgls
systemd-cgls \
systemd-stdio-bridge \
systemd-nspawn
dist_bin_SCRIPTS = \
src/systemd-analyze
if HAVE_GTK
bin_PROGRAMS += \
@ -138,13 +143,17 @@ rootlibexec_PROGRAMS = \
systemd-timestamp \
systemd-ac-power \
systemd-detect-virt \
systemd-sysctl
systemd-sysctl \
systemd-binfmt
systemgenerator_PROGRAMS = \
systemd-getty-generator
if HAVE_LIBCRYPTSETUP
rootlibexec_PROGRAMS += \
systemd-cryptsetup
systemgenerator_PROGRAMS = \
systemgenerator_PROGRAMS += \
systemd-cryptsetup-generator
endif
@ -192,13 +201,20 @@ dbusinterface_DATA = \
org.freedesktop.systemd1.Path.xml
dist_bashcompletion_DATA = \
src/systemctl-bash-completion.sh
src/systemctl-bash-completion.sh
dist_tmpfiles_DATA = \
tmpfiles.d/systemd.conf \
tmpfiles.d/x11.conf
if HAVE_SYSV_COMPAT
dist_tmpfiles_DATA += \
tmpfiles.d/legacy.conf
endif
dist_systemunit_DATA = \
units/graphical.target \
units/multi-user.target \
units/emergency.service \
units/emergency.target \
units/sysinit.target \
@ -216,14 +232,13 @@ dist_systemunit_DATA = \
units/reboot.target \
units/rescue.target \
units/rpcbind.target \
units/rtc-set.target \
units/time-sync.target \
units/shutdown.target \
units/final.target \
units/umount.target \
units/sigpwr.target \
units/sockets.target \
units/swap.target \
units/dbus.target \
units/systemd-initctl.socket \
units/systemd-logger.socket \
units/systemd-shutdownd.socket \
@ -238,7 +253,6 @@ dist_systemunit_DATA = \
units/sys-kernel-debug.mount \
units/sys-kernel-security.automount \
units/sys-kernel-security.mount \
units/var-lock.mount \
units/var-run.mount \
units/media.mount \
units/hwclock-load.service \
@ -252,14 +266,19 @@ dist_systemunit_DATA = \
units/systemd-tmpfiles-clean.timer \
units/quotaon.service \
units/systemd-ask-password-wall.path \
units/systemd-ask-password-console.path
units/systemd-ask-password-console.path \
units/syslog.target
if HAVE_SYSV_COMPAT
dist_systemunit_DATA += \
units/var-lock.mount
endif
nodist_systemunit_DATA = \
units/getty@.service \
units/serial-getty@.service \
units/graphical.target \
units/console-shell.service \
units/remote-fs.target \
units/multi-user.target \
units/systemd-initctl.service \
units/systemd-logger.service \
units/systemd-shutdownd.service \
@ -280,7 +299,7 @@ nodist_systemunit_DATA = \
units/systemd-ask-password-wall.service \
units/systemd-ask-password-console.service \
units/systemd-sysctl.service \
units/syslog.target \
units/systemd-binfmt.service \
units/halt.service \
units/poweroff.service \
units/reboot.service \
@ -301,8 +320,7 @@ nodist_userunit_DATA = \
EXTRA_DIST = \
units/getty@.service.m4 \
units/serial-getty@.service.m4 \
units/graphical.target.m4 \
units/multi-user.target.m4 \
units/console-shell.service.m4 \
units/remote-fs.target.m4 \
units/rescue.service.m4 \
units/systemd-initctl.service.in \
@ -325,7 +343,7 @@ EXTRA_DIST = \
units/systemd-ask-password-wall.service.in \
units/systemd-ask-password-console.service.in \
units/systemd-sysctl.service.in \
units/syslog.target.in \
units/systemd-binfmt.service.in \
units/halt.service.in \
units/poweroff.service.in \
units/reboot.service.in \
@ -335,7 +353,8 @@ EXTRA_DIST = \
units/fsck-root.service.in \
units/quotacheck.service.in \
systemd.pc.in \
introspect.awk
introspect.awk \
src/org.freedesktop.systemd1.policy.in
if TARGET_FEDORA
dist_systemunit_DATA += \
@ -351,6 +370,11 @@ dist_systemunit_DATA += \
units/fedora/halt-local.service
endif
if TARGET_FRUGALWARE
dist_systemunit_DATA += \
units/frugalware/display-manager.service
endif
if HAVE_PLYMOUTH
dist_systemunit_DATA += \
units/plymouth-start.service \
@ -382,7 +406,7 @@ dist_doc_DATA = \
pkgconfigdata_DATA = \
systemd.pc
dist_polkitpolicy_DATA = \
polkitpolicy_DATA = \
src/org.freedesktop.systemd1.policy
noinst_LTLIBRARIES = \
@ -487,6 +511,7 @@ EXTRA_DIST += \
${libsystemd_core_la_SOURCES:.c=.h} \
${libsystemd_daemon_la_SOURCES:.c=.h} \
src/macro.h \
src/def.h \
src/ioprio.h \
src/missing.h \
src/list.h \
@ -510,6 +535,7 @@ MANPAGES = \
man/systemctl.1 \
man/systemadm.1 \
man/systemd-cgls.1 \
man/systemd-nspawn.1 \
man/systemd-tmpfiles.8 \
man/systemd-notify.1 \
man/sd_notify.3 \
@ -544,7 +570,9 @@ MANPAGES = \
man/vconsole.conf.5 \
man/locale.conf.5 \
man/os-release.5 \
man/modules-load.d.5
man/modules-load.d.5 \
man/binfmt.d.5 \
man/sysctl.d.5
MANPAGES_ALIAS = \
man/reboot.8 \
@ -774,6 +802,15 @@ systemd_sysctl_CFLAGS = \
systemd_sysctl_LDADD = \
libsystemd-basic.la
systemd_binfmt_SOURCES = \
src/binfmt.c
systemd_binfmt_CFLAGS = \
$(AM_CFLAGS)
systemd_binfmt_LDADD = \
libsystemd-basic.la
systemd_fsck_SOURCES = \
src/fsck.c \
src/dbus-common.c
@ -850,6 +887,16 @@ systemd_cryptsetup_generator_CFLAGS = \
systemd_cryptsetup_generator_LDADD = \
libsystemd-basic.la
systemd_getty_generator_SOURCES = \
src/getty-generator.c \
src/unit-name.c
systemd_getty_generator_CFLAGS = \
$(AM_CFLAGS)
systemd_getty_generator_LDADD = \
libsystemd-basic.la
systemd_user_sessions_SOURCES = \
src/user-sessions.c \
src/cgroup-util.c
@ -978,6 +1025,23 @@ systemd_cgls_CFLAGS = \
systemd_cgls_LDADD = \
libsystemd-basic.la
systemd_nspawn_SOURCES = \
src/nspawn.c \
src/cgroup-util.c
systemd_nspawn_CFLAGS = \
$(AM_CFLAGS)
systemd_nspawn_LDADD = \
libsystemd-basic.la \
libsystemd-daemon.la
systemd_stdio_bridge_SOURCES = \
src/bridge.c
systemd_stdio_bridge_LDADD = \
libsystemd-basic.la
systemadm_SOURCES = \
src/systemadm.vala \
src/systemd-interfaces.vala
@ -1058,13 +1122,15 @@ pam_systemd_la_LIBADD = \
SED_PROCESS = \
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
$(SED) -e 's,@rootlibexecdir\@,$(rootlibexecdir),g' \
-e 's,@rootbindir\@,$(rootbindir),g' \
-e 's,@SPECIAL_SYSLOG_SERVICE\@,$(SPECIAL_SYSLOG_SERVICE),g' \
-e 's,@rootbindir\@,$(rootbindir),g' \
-e 's,@bindir\@,$(bindir),g' \
-e 's,@SYSTEMCTL\@,$(rootbindir)/systemctl,g' \
-e 's,@SYSTEMD_NOTIFY\@,$(rootbindir)/systemd-notify,g' \
-e 's,@pkgsysconfdir\@,$(pkgsysconfdir),g' \
-e 's,@pkgdatadir\@,$(pkgdatadir),g' \
-e 's,@pkglibexecdir\@,$(pkglibexecdir),g' \
-e 's,@systemunitdir\@,$(systemunitdir),g' \
-e 's,@userunitdir\@,$(userunitdir),g' \
-e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \
-e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \
-e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' \
@ -1080,6 +1146,9 @@ man/%: man/%.in Makefile
%.pc: %.pc.in Makefile
$(SED_PROCESS)
src/%.policy: src/%.policy.in Makefile
$(SED_PROCESS)
M4_PROCESS_SYSTEM = \
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
$(M4) -P $(M4_DISTRO_FLAG) -DFOR_SYSTEM=1 < $< > $@ || rm $@
@ -1099,7 +1168,8 @@ CLEANFILES = \
$(nodist_userunit_DATA) \
$(nodist_man_MANS) \
${XML_IN_FILES:.xml.in=.html} \
$(pkgconfigdata_DATA)
$(pkgconfigdata_DATA) \
src/org.freedesktop.systemd1.policy
if HAVE_VALAC
CLEANFILES += \
@ -1183,6 +1253,14 @@ CLEANFILES += \
$(dbusinterface_DATA)
install-data-hook:
$(MKDIR_P) -m 0755 \
$(DESTDIR)$(tmpfilesdir) \
$(DESTDIR)$(sysconfdir)/modules-load.d \
$(DESTDIR)$(sysconfdir)/sysctl.d \
$(DESTDIR)$(sysconfdir)/binfmt.d \
$(DESTDIR)$(systemshutdowndir) \
$(DESTDIR)$(systemgeneratordir) \
$(DESTDIR)$(usergeneratordir)
$(MKDIR_P) -m 0755 \
$(DESTDIR)$(systemunitdir) \
$(DESTDIR)$(userunitdir) \
@ -1241,13 +1319,11 @@ install-data-hook:
fsck-root.service \
remount-rootfs.service \
var-run.mount \
var-lock.mount \
media.mount && \
$(LN_S) ../systemd-remount-api-vfs.service systemd-remount-api-vfs.service && \
$(LN_S) ../fsck-root.service fsck-root.service && \
$(LN_S) ../remount-rootfs.service remount-rootfs.service && \
$(LN_S) ../var-run.mount var-run.mount && \
$(LN_S) ../var-lock.mount var-lock.mount && \
$(LN_S) ../media.mount media.mount )
( cd $(DESTDIR)$(userunitdir) && \
rm -f shutdown.target sockets.target local-fs.target swap.target bluetooth.target printer.target sound.target && \
@ -1284,10 +1360,6 @@ install-data-hook:
$(LN_S) $(systemunitdir)/getty@.service getty@tty4.service && \
$(LN_S) $(systemunitdir)/getty@.service getty@tty5.service && \
$(LN_S) $(systemunitdir)/getty@.service getty@tty6.service )
( cd $(DESTDIR)$(pkgsysconfdir)/system/local-fs.target.wants && \
rm -f quotaon.service quotacheck.service && \
$(LN_S) $(systemunitdir)/quotacheck.service quotacheck.service && \
$(LN_S) $(systemunitdir)/quotaon.service quotaon.service )
( cd $(DESTDIR)$(pkgsysconfdir)/system/multi-user.target.wants && \
rm -f remote-fs.target && \
$(LN_S) $(systemunitdir)/remote-fs.target remote-fs.target )
@ -1305,6 +1377,7 @@ install-data-hook:
systemd-random-seed-load.service \
systemd-tmpfiles-setup.service \
systemd-sysctl.service \
systemd-binfmt.service \
systemd-ask-password-console.path \
systemd-kmsg-syslogd.service \
cryptsetup.target && \
@ -1318,6 +1391,7 @@ install-data-hook:
$(LN_S) ../systemd-random-seed-load.service systemd-random-seed-load.service && \
$(LN_S) ../systemd-tmpfiles-setup.service systemd-tmpfiles-setup.service && \
$(LN_S) ../systemd-sysctl.service systemd-sysctl.service && \
$(LN_S) ../systemd-binfmt.service systemd-binfmt.service && \
$(LN_S) ../systemd-ask-password-console.path systemd-ask-password-console.path && \
$(LN_S) ../systemd-kmsg-syslogd.service && \
$(LN_S) ../cryptsetup.target cryptsetup.target )
@ -1365,8 +1439,9 @@ if TARGET_FEDORA
rm -f halt-local.service && \
$(LN_S) $(systemunitdir)/halt-local.service halt-local.service )
( cd $(DESTDIR)$(systemunitdir) && \
rm -f display-manager.service && \
$(LN_S) prefdm.service display-manager.service )
rm -f display-manager.service single.service && \
$(LN_S) prefdm.service display-manager.service && \
$(LN_S) rescue.service single.service )
( cd $(DESTDIR)$(systemunitdir)/graphical.target.wants && \
rm -f display-manager.service && \
$(LN_S) $(systemunitdir)/display-manager.service display-manager.service )
@ -1381,8 +1456,10 @@ if TARGET_MANDRIVA
rm -f halt-local.service && \
$(LN_S) $(systemunitdir)/halt-local.service halt-local.service )
( cd $(DESTDIR)$(systemunitdir) && \
rm -f display-manager.service && \
$(LN_S) prefdm.service display-manager.service )
rm -f display-manager.service dm.service single.service && \
$(LN_S) prefdm.service display-manager.service && \
$(LN_S) prefdm.service dm.service && \
$(LN_S) rescue.service single.service )
( cd $(DESTDIR)$(systemunitdir)/graphical.target.wants && \
rm -f display-manager.service && \
$(LN_S) $(systemunitdir)/display-manager.service display-manager.service )
@ -1394,6 +1471,12 @@ if TARGET_DEBIAN_OR_UBUNTU
$(LN_S) multi-user.target runlevel5.target )
endif
if HAVE_SYSV_COMPAT
( cd $(DESTDIR)$(systemunitdir)/local-fs.target.wants && \
rm -f var-lock.mount && \
$(LN_S) ../var-lock.mount var-lock.mount )
endif
DISTCHECK_CONFIGURE_FLAGS = \
--with-dbuspolicydir=$$dc_install_base/$(dbuspolicydir) \
--with-dbussessionservicedir=$$dc_install_base/$(dbussessionservicedir) \

146
TODO
View File

@ -2,28 +2,113 @@ F15:
* swap units that are activated by one name but shown in the kernel under another are semi-broken
* dep cycle basic → udev-retry → auditd → iptables → basic
* isolate multi-user.target doesn't start a getty@tty1 if we run it from graphical.target
https://bugzilla.redhat.com/show_bug.cgi?id=688661
* finish syslog socket stuff
* NFS, networkmanager ordering issue (PENDING)
* NFS, networkmanager ordering issue
* NM should pull in network.target (PENDING)
https://bugzilla.redhat.com/show_bug.cgi?id=692008
* ntpd should pull in time-sync.target. (PENDING)
* add fstab fields to add wait timeouts, change Wants to Requires by local-fs.target
* hook emergency.target into local-fs.target in some way as OnFailure with isolate
* mount /dev/.run and /var/run as bind mounts
* bind mounts are ignored
https://bugzilla.redhat.com/show_bug.cgi?id=682662
* Make use of UnknownInterface
* 0595f9a1c182a84581749823ef47c5f292e545f9 is borked, freezes shutdown
(path: after installing inotify watches, recheck file again to fix race)
* support chkconfig without forwarding to systemctl to facilitate upgrades
* bluetooth should be possible to disable
* drop SIGHUP handling from rsyslog.service upstream
* fix alsa mixer restore to not print error when no config is stored
Features:
* don't trim empty cgroups
https://bugzilla.redhat.com/show_bug.cgi?id=678555
* serialize used job ids and max job id
* show enablement status in systemctl status
* expose monotonic timestamps on the bus and make systemd-analyze use it
* write blog stories about:
- chroot, nspawn and friends
- the blame game: systemd-analyze
- enabling dbus services
- status update
* allow port = 0 in .socket units
* rename systemd-logger to systemd-stdio-syslog-bridge
* introduce /usr/lib/binfmt.d/, /usr/lib/tmpfiles.d/
* in pam_systemd: don't rely on /proc/self/loginuid in a container
* take BSD file lock on tty devices when using them?
* tmpfiles should allow two identical lines
https://bugzilla.redhat.com/show_bug.cgi?id=690253
* avoid any flag files, or readahead files in /, we need to support r/o /
or / on tmpfs like Android setups.
* teach dbus to activate all services it finds in /etc/systemd/services/org-*.service
* get process transport into dbus for systemctl -P/-H
* document default dependencies
* support systemd.whitelist=/systemd.blacklist= on the kernel command
line.
* Find a way to replace /var/run, /var/lock directories with
symlinks during an RPM package upgrade (filesystem.rpm or systemd.rpm).
We soon want to get rid of var-run.mount var-lock.mount units.
* when key file cannot be found, read it from kbd in cryptsetup
* get rid of random file name in generator directory?
/run/systemd/generator-IH1vFu
* add switch to systemctl to show enabled but not running services. Or
another switch that shows service that have been running since
booting but aren't running anymore.
* reuse mkdtemp namespace dirs in /tmp?
* don't strip facility from kmsg log messages as soon as that is possible:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=9d90c8d9cde929cbc575098e825d7c29d9f45054
* recreate systemd's D-Bus private socket file on SIGUSR2
* be more specific what failed:
...
Unmounting file systems.
Not all file systems unmounted, 1 left.
Disabling swaps.
Detaching loop devices.
Detaching DM devices.
Cannot finalize remaining file systems and devices, trying to kill remaining processes.
Unmounting file systems.
Not all file systems unmounted, 1 left.
Cannot finalize remaining file systems and devices, giving up.
...
* check for compiled-in, but not active selinux, and don't print any warnings
about policy loading. Probably check for available selinux in /proc/filesystems,
and check for active selinux with getcon_raw() == "kernel"
* optionally create watched directories in .path units
* Support --test based on current system state
* consider services with no [Install] section and stored in /lib enabled by "systemctl is-enabled"
* consider services with any kind of link in /etc/systemd/system enabled
@ -32,17 +117,21 @@ Features:
* make sure timeouts are applied to Type=oneshot services.
* maybe implement "systemctl mask" and "systemctl unmask", but not
* Maybe implement "systemctl mask" and "systemctl unmask", but not
document it? When doing that add switch to make this temporary by
placing mask links in /dev.
Consider moving the actual fs operations into systemd behind a D-Bus
interface, to make namespaces/containers/remote connections work properly.
* detect LXC environment
* invoke vhangup() before and after invoking getty
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3c95c985fa91ecf6a0e29622bbdd13dcfc5ce9f1
* support "auto" and "comment=systemd.automount" at the same time for an fstab entry
* Maybe store in unit files whether a service should be enabled by default on package installation
(belongs into a distro pattern though, not in an upstream package's service file)
* perhaps add "systemctl reenable" as combination of "systemctl disable" and "systemctl enable"
@ -55,7 +144,7 @@ Features:
* Patch systemd-fsck to use -C and pass console fd to it
* support remote/ssh systemctl/systemadm, and local privileged access
* support remote/ssh systemctl/systemadm, and local privileged access → dbus patches need to be merged
* configurable jitter for timer events
@ -74,32 +163,28 @@ Features:
- get PR_SET_ANCHOR merged: http://lkml.org/lkml/2010/2/2/165
* add VT tracking:
- provide CK functionality
- start getty only when actual vt switch happens (same model as
socket on-demand activation). allocate the next free tty and
start a getty there. this way, pressing alt-f[1-12] will switch
through running X and getty sessions, and any unallocated
activated tty will start a new getty. the hardcoding of
getty[1-6] will entirely go away.
- http://git.kernel.org/?p=linux/kernel/git/gregkh/tty-2.6.git;a=commitdiff;h=fbc92a3455577ab17615cbcb91826399061bd789
- provide CK functionality
- start getty only when actual vt switch happens (same model as
socket on-demand activation). allocate the next free tty and
start a getty there. this way, pressing alt-f[1-12] will switch
through running X and getty sessions, and any unallocated
activated tty will start a new getty. the hardcoding of
getty[1-6] will entirely go away.
- http://git.kernel.org/?p=linux/kernel/git/gregkh/tty-2.6.git;a=commitdiff;h=fbc92a3455577ab17615cbcb91826399061bd789
* implicitly import "defaults" settings file into all types
* port over to LISTEN_FDS/LISTEN_PID:
- uuidd DONE
- dbus DONE
- rsyslog DONE
- rpcbind (/var/run/rpcbind.sock!) DONE
- cups DONE
- avahi-daemon (/var/run/avahi-daemon/socket) DONE
- ssh CLASSIC
- uuidd HAVEPATCH
- rpcbind (/var/run/rpcbind.sock!) HAVEPATCH
- cups HAVEPATCH
- postfix, saslauthd
- apache/samba
- libvirtd (/var/run/libvirt/libvirt-sock-ro)
- bluetoothd (/var/run/sdp! @/org/bluez/audio!)
- distccd
* fingerprint.target, wireless.target, gps.target
* fingerprint.target, wireless.target, gps.target, netdevice.target
* set_put(), hashmap_put() return values check. i.e. == 0 doesn't free()!
@ -115,16 +200,12 @@ Features:
* add systemctl switch to dump transaction without executing it
* suspend, resume
* suspend, resume support?
* readahead: btrfs/LVM SSD detection
* add separate man page for [Install] settings
* only add quotacheck deps to .mount units which mention grpquota/usrquota in the mount flags
* systemctl condrestart should return 0 if service isn't running
* allow runtime changing of log level and target
External:
@ -133,7 +214,7 @@ External:
* snd-seq should go, https://bugzilla.redhat.com/show_bug.cgi?id=676095
* gnome-shell python script/glxinfo/is-accelerated wech
* gnome-shell python script/glxinfo/is-accelerated must die
* make cryptsetup lower --iter-time
@ -141,6 +222,7 @@ External:
* patch kernel for cpu feature modalias for autoloading aes/kvm/...
http://git.kernel.org/?p=linux/kernel/git/ak/linux-misc-2.6.git;a=shortlog;h=refs/heads/cpuid-match
(Rafael J. Wysocki's sysdev rework is on the way. After that CPUs can be exported a proper bus.)
* procps, psmisc, sysvinit-tools, hostname → util-linux-ng

View File

@ -66,7 +66,7 @@ else
run_versioned automake "$AM_VERSION" --copy --foreign --add-missing
if [ "x$1" != "xac" ]; then
CFLAGS="$CFLAGS -g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --with-rootdir= "$@"
CFLAGS="$CFLAGS -g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --with-rootdir= --libexecdir=/usr/lib "$@"
make clean
fi
fi

View File

@ -17,7 +17,7 @@
AC_PREREQ(2.63)
AC_INIT([systemd],[20],[systemd-devel@lists.freedesktop.org])
AC_INIT([systemd],[24],[systemd-devel@lists.freedesktop.org])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@ -28,6 +28,9 @@ AC_SUBST(PACKAGE_URL, [http://www.freedesktop.org/wiki/Software/systemd])
AC_CANONICAL_HOST
AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
AS_IF([test "x$host_cpu" = "xmips" || test "x$host_cpu" = "xmipsel" ||
test "x$host_cpu" = "xmips64" || test "x$host_cpu" = "xmips64el"],
[AC_DEFINE(ARCH_MIPS, [], [Whether on mips arch])])
AM_SILENT_RULES([yes])
@ -294,30 +297,15 @@ fi
with_distro=`echo ${with_distro} | tr '[[:upper:]]' '[[:lower:]]' `
AC_DEFINE_UNQUOTED(DISTRIBUTION, ["${with_distro}"], [Target Distribution])
# Default generic names
SPECIAL_SYSLOG_SERVICE=syslog.service
# Location of the init scripts as mandated by LSB
SYSTEM_SYSVINIT_PATH=/etc/init.d
SYSTEM_SYSVRCND_PATH=/etc/rc.d
M4_DISTRO_FLAG=
case $with_distro in
fedora)
SYSTEM_SYSVINIT_PATH=/etc/rc.d/init.d
SYSTEM_SYSVRCND_PATH=/etc/rc.d
# A little background why we define this special unit
# names here in configure.ac: SysV services currently
# cannot have aliases. As long as syslog is started
# via a SysV init script we hence define this name to
# the actual SysV name here. Later on when SysV init
# scripts are not used anymore it is advisable to use
# the generic name instead and use symlinks in the
# unit directories to point to the right native unit
# file.
SPECIAL_SYSLOG_SERVICE=rsyslog.service
AC_DEFINE(TARGET_FEDORA, [], [Target is Fedora/RHEL])
M4_DISTRO_FLAG=-DTARGET_FEDORA=1
have_plymouth=true
@ -330,61 +318,49 @@ case $with_distro in
;;
debian)
SYSTEM_SYSVRCND_PATH=/etc
SPECIAL_SYSLOG_SERVICE=rsyslog.service
AC_DEFINE(TARGET_DEBIAN, [], [Target is Debian])
M4_DISTRO_FLAG=-DTARGET_DEBIAN=1
;;
ubuntu)
SYSTEM_SYSVRCND_PATH=/etc
SPECIAL_SYSLOG_SERVICE=rsyslog.service
AC_DEFINE(TARGET_UBUNTU, [], [Target is Ubuntu])
M4_DISTRO_FLAG=-DTARGET_UBUNTU=1
;;
arch)
SYSTEM_SYSVINIT_PATH=/etc/rc.d
SYSTEM_SYSVRCND_PATH=/etc
SPECIAL_SYSLOG_SERVICE=syslog-ng.service
AC_DEFINE(TARGET_ARCH, [], [Target is ArchLinux])
M4_DISTRO_FLAG=-DTARGET_ARCH=1
;;
gentoo)
SYSTEM_SYSVINIT_PATH=
SYSTEM_SYSVRCND_PATH=
SPECIAL_SYSLOG_SERVICE=syslog-ng.service
AC_DEFINE(TARGET_GENTOO, [], [Target is Gentoo])
M4_DISTRO_FLAG=-DTARGET_GENTOO=1
;;
slackware)
SYSTEM_SYSVINIT_PATH=/etc/rc.d/init.d
SYSTEM_SYSVRCND_PATH=/etc/rc.d
AC_DEFINE(TARGET_SLACKWARE, [], [Target is Slackware])
M4_DISTRO_FLAG=-DTARGET_SLACKWARE=1
;;
frugalware)
SYSTEM_SYSVINIT_PATH=/etc/rc.d
SYSTEM_SYSVRCND_PATH=/etc/rc.d
AC_DEFINE(TARGET_FRUGALWARE, [], [Target is Frugalware])
M4_DISTRO_FLAG=-DTARGET_FRUGALWARE=1
;;
altlinux)
SYSTEM_SYSVINIT_PATH=/etc/rc.d/init.d
SYSTEM_SYSVRCND_PATH=/etc/rc.d
SPECIAL_SYSLOG_SERVICE=syslogd.service
AC_DEFINE(TARGET_ALTLINUX, [], [Target is ALTLinux])
M4_DISTRO_FLAG=-DTARGET_ALTLINUX=1
have_plymouth=true
;;
mandriva)
SYSTEM_SYSVINIT_PATH=/etc/rc.d/init.d
SYSTEM_SYSVRCND_PATH=/etc/rc.d
SPECIAL_SYSLOG_SERVICE=rsyslog.service
AC_DEFINE(TARGET_MANDRIVA, [], [Target is Mandriva])
M4_DISTRO_FLAG=-DTARGET_MANDRIVA=1
have_plymouth=true
;;
other)
AS_IF([test "x$with_syslog_service" = "x"],
[AC_MSG_ERROR([With --distro=other, you must pass --with-syslog-service= to configure])])
;;
*)
AC_MSG_ERROR([Your distribution (${with_distro}) is not yet supported, SysV init scripts could not be found! (patches welcome); you can specify --with-distro=other to skip this check])
@ -403,15 +379,8 @@ AC_ARG_WITH([sysvrcd-path],
[SYSTEM_SYSVRCND_PATH="$withval"],
[])
AC_ARG_WITH([syslog-service],
[AS_HELP_STRING([--with-syslog-service=UNIT],
[Specify the name of the special syslog service @<:@default=based on distro@:>@])],
[SPECIAL_SYSLOG_SERVICE="$withval"],
[])
AC_SUBST(SYSTEM_SYSVINIT_PATH)
AC_SUBST(SYSTEM_SYSVRCND_PATH)
AC_SUBST(SPECIAL_SYSLOG_SERVICE)
AC_SUBST(M4_DISTRO_FLAG)
if test "x${SYSTEM_SYSVINIT_PATH}" != "x" -a "x${SYSTEM_SYSVRCND_PATH}" != "x"; then
@ -442,8 +411,7 @@ AM_CONDITIONAL(TARGET_ALTLINUX, test x"$with_distro" = xaltlinux)
AM_CONDITIONAL(TARGET_MANDRIVA, test x"$with_distro" = xmandriva)
AM_CONDITIONAL(HAVE_PLYMOUTH, test -n "$have_plymouth")
AC_DEFINE_UNQUOTED(SPECIAL_SYSLOG_SERVICE, ["$SPECIAL_SYSLOG_SERVICE"], [Syslog service name])
AM_CONDITIONAL(HAVE_SYSV_COMPAT, test "$SYSTEM_SYSV_COMPAT" = "yes")
AC_ARG_WITH([dbuspolicydir],
AS_HELP_STRING([--with-dbuspolicydir=DIR], [D-Bus policy directory]),
@ -498,7 +466,6 @@ echo "
SysV compatibility: ${SYSTEM_SYSV_COMPAT}
SysV init scripts: ${SYSTEM_SYSVINIT_PATH}
SysV rc?.d directories: ${SYSTEM_SYSVRCND_PATH}
Syslog service: ${SPECIAL_SYSLOG_SERVICE}
Gtk: ${have_gtk}
libcryptsetup: ${have_libcryptsetup}
tcpwrap: ${have_tcpwrap}

103
man/binfmt.d.xml Normal file
View File

@ -0,0 +1,103 @@
<?xml version="1.0"?>
<!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="binfmt.d">
<refentryinfo>
<title>binfmt.d</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>binfmt.d</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>binfmt.d</refname>
<refpurpose>Configure additional binary formats at boot</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>/etc/binfmt.d/*.conf</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd</command> uses
<filename>/etc/binfmt.d/</filename> to configure
additional binary formats to register during boot in
the kernel. Each configuration file is named in the
style of
<filename>/etc/binfmt.d/&lt;program&gt;.conf</filename>.</para>
</refsect1>
<refsect1>
<title>Configuration Format</title>
<para>Each file contains a list of binfmt_misc kernel
binary format rules. Consult <ulink
url="http://www.kernel.org/doc/Documentation/binfmt_misc.txt">binfmt_misc.txt</ulink>
for more information on registration of additional
binary formats and how to write rules.</para>
<para>Empty lines and lines beginning with ; and # are
ignored. Note that this means you may not use ; and #
as delimiter in binary format rules.</para>
<para>Configuration files are loaded in alphabetical
order. To ensure that a specific rule takes precedence
over another place it in a file with an alphabetically
later name.</para>
</refsect1>
<refsect1>
<title>Example</title>
<example>
<title>/etc/binfmt.d/wine.conf example:</title>
<programlisting># Start WINE on Windows executables
:DOSWin:M::MZ::/usr/bin/wine:</programlisting>
</example>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>wine</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -128,7 +128,7 @@
<para><filename>/etc/locale.conf:</filename></para>
<programlisting>LANG=de_DE.UTF-8
LC_MESSAGE=C</programlisting>
LC_MESSAGES=C</programlisting>
</example>
</refsect1>

View File

@ -4,7 +4,7 @@
<!--
This file is part of systemd.
Copyright 2010 Brandon Philips
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
@ -77,10 +77,10 @@
<refsect1>
<title>Example</title>
<example>
<title>/etc/modules-load.d/uinput.conf example:</title>
<title>/etc/modules-load.d/virtio-net.conf example:</title>
<programlisting># Load uinput.ko at boot
uinput</programlisting>
<programlisting># Load virtio-net.ko at boot
virtio-net</programlisting>
</example>
</refsect1>

View File

@ -65,7 +65,7 @@
<orderedlist>
<listitem><para>If it does not exist yet, the
user runtime directory
<filename>/var/run/user/$USER</filename> is
<filename>/run/user/$USER</filename> is
created and its ownership changed to the user
that is logging in.</para></listitem>
@ -284,7 +284,6 @@
<option>create-session=1</option>,
<option>kill-session=0</option>,
<option>kill-user=0</option>,
<option>keep-root=1</option>,
<option>reset-controllers=cpu</option>,
<option>kill-only-users=</option>,
<option>kill-exclude-users=root</option>.</para>

View File

@ -123,7 +123,7 @@
reference implementation.</para>
<para>Internally, this function creates a file in
<filename>/dev/.systemd/readahead/</filename> which is
<filename>/run/systemd/readahead/</filename> which is
then used as flag file to notify the read-ahead
subsystem.</para>

95
man/sysctl.d.xml Normal file
View File

@ -0,0 +1,95 @@
<?xml version="1.0"?>
<!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sysctl.d">
<refentryinfo>
<title>sysctl.d</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>sysctl.d</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>sysctl.d</refname>
<refpurpose>Configure kernel parameters at boot</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>/etc/sysctl.d/*.conf</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd</command> uses
<filename>/etc/sysctl.d/</filename> to configure
<citerefentry><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>
kernel parameters to load during boot. Each
configuration file is named in the style of
<filename>/etc/sysctl.d/&lt;program&gt;.conf</filename>.</para>
</refsect1>
<refsect1>
<title>Configuration Format</title>
<para>The configuration files should simply contain a
list of variable assignments, separated by
newlines. Empty lines and lines whose first
non-whitespace character is # or ; are ignored.</para>
<para>Note that both / and . are accepted as
separators in sysctl variable names.</para>
</refsect1>
<refsect1>
<title>Example</title>
<example>
<title>/etc/sysctl.d/domain-name.conf example:</title>
<programlisting># Set kernel YP domain name
kernel.domainname=example.com</programlisting>
</example>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sysctl.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -304,13 +304,11 @@
<command>kill</command>, choose the
mode how to kill the selected
processes. Must be one of
<option>control-group</option>,
<option>process-group</option> or
<option>control-group</option> or
<option>process</option> to select
whether to kill the entire control
group, the process group or only the
selected process itself. If omitted
defaults to
group or only the selected process
itself. If omitted defaults to
<option>control-group</option> if
<option>--kill-who=all</option> is
set, or <option>process</option>
@ -382,6 +380,27 @@
file that shall be
disabled.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-H</option></term>
<term><option>--host</option></term>
<listitem><para>Execute operation
remotely. Specifiy a hostname, or
username and hostname seperated by @,
to connect to. This will use SSH to
talk to the remote systemd
instance.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-P</option></term>
<term><option>--privileged</option></term>
<listitem><para>Acquire privileges via
PolicyKit before executing the
operation.</para></listitem>
</varlistentry>
</variablelist>
<para>The following commands are understood:</para>
@ -447,9 +466,9 @@
<listitem><para>Restart one or more
units specified on the command
line. If the units are not running yet
the operation will
fail. Note that for compatibility
line if the units are running. Do
nothing if units are not running.
Note that for compatibility
with Red Hat init scripts
<command>condrestart</command> is
equivalent to this command.</para></listitem>
@ -468,12 +487,13 @@
<listitem><para>Reload one or more
units if they support it. If not,
restart them instead. If the units
are not running yet the operation
will fail. Note that for
compatibility with SysV init scripts
restart them instead. Do nothing if
the units are not running. Note that
for compatibility with SysV init
scripts
<command>force-reload</command> is
equivalent to this command.</para></listitem>
equivalent to this
command.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>isolate [NAME]</command></term>

190
man/systemd-nspawn.xml Normal file
View File

@ -0,0 +1,190 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-nspawn">
<refentryinfo>
<title>systemd-nspawn</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-nspawn</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-nspawn</refname>
<refpurpose>Spawn a namespace container for debugging, testing and building</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>systemd-nspawn <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt">COMMAND</arg> <arg choice="opt" rep="repeat">ARGS</arg></command>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-nspawn</command> may be used to
run a command or OS in a light-weight namespace
container. In many ways it is similar to
<citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
but more powerful since it fully virtualizes the file
system hierachy, as well as the process tree, the
various IPC subsystems and the host and domain
name.</para>
<para><command>systemd-nspawn</command> limits access
to various kernel interfaces in the container to
read-only, such as <filename>/sys</filename>,
<filename>/proc/sys</filename> or
<filename>/selinux</filename>. Network interfaces and
the system clock may not be changed from within the
container. Device nodes may not be created. The host
system cannot be rebooted and kernel modules may not
be loaded from within the container.</para>
<para>Note that even though these security precautions
are taken <command>systemd-nspawn</command> is not
suitable for secure container setups. Many of the
security features may be circumvented and are hence
primarily useful to avoid accidental changes to the
host system from the container. The intended use of
this program is debugging and testing as well as
building of packages, distributions and software
involved with boot and systems management.</para>
<para>In contrast to
<citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
<command>systemd-nspawn</command> may be used to boot
full Linux-based operating systems in a
container.</para>
<para>Use a tool like
<citerefentry><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry> or <citerefentry><refentrytitle>mock</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to set up an OS directory tree suitable as file system
hierarchy for <command>systemd-nspawn</command> containers.</para>
<para>Note that <command>systemd-nspawn</command> will
mount file systems private to the container to
<filename>/dev</filename>,
<filename>/run</filename> and similar. These will
not be visible outside of the container, and their
contents will be lost when the container exits.</para>
<para>Note that running two
<command>systemd-nspawn</command> containers from the
same directory tree will not make processes in them
see each other. The PID namespace seperation of the
two containers is complete and the containers will
share very few runtime objects except for the
underlying file system.</para>
</refsect1>
<refsect1>
<title>Options</title>
<para>If no arguments are passed the container is set
up and a shell started in it, otherwise the passed
command and arguments are executed in it. The
following options are understood:</para>
<variablelist>
<varlistentry>
<term><option>--help</option></term>
<listitem><para>Prints a short help
text and exits.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--directory=</option></term>
<term><option>--D</option></term>
<listitem><para>Directory to use as
file system root for the namespace
container. If omitted the current
directory will be
used.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Example 1</title>
<programlisting># debootstrap --arch=amd64 unstable debian-tree/
# systemd-nspawn -D debian-tree/</programlisting>
<para>This installs a minimal Debian unstable
distribution into the directory
<filename>debian-tree/</filename> and then spawns a
shell in a namespace container in it.</para>
</refsect1>
<refsect1>
<title>Example 2</title>
<programlisting># mock --init
# systemd-nspawn -D /var/lib/mock/fedora-rawhide-x86_64/root/ /bin/systemd systemd.log_level=debug</programlisting>
<para>This installs a minimal Fedora distribution into
a subdirectory of <filename>/var/lib/mock/</filename>
and then boots an OS in a namespace container in it,
with systemd as init system, configured for debug
logging.</para>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>The exit code of the program executed in the
container is returned.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<citerefentry><refentrytitle>mock</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -558,7 +558,10 @@
various resource limits for executed
processes. See
<citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for details.</para></listitem>
for details. Use the string
<varname>infinity</varname> to
configure no limit on a specific
resource.</para></listitem>
</varlistentry>
<varlistentry>
@ -597,16 +600,34 @@
</varlistentry>
<varlistentry>
<term><varname>Capabilities=</varname></term>
<listitem><para>Controls the
<term><varname>CapabilityBoundingSet=</varname></term>
<listitem><para>Controls which
capabilities to include in the
capability bounding set for the
executed process. See
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
set for the executed process. Take a
capability string as described in
<citerefentry><refentrytitle>cap_from_text</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
Note that this capability set is
usually influenced by the capabilities
attached to the executed
file.</para></listitem>
for details. Takes a whitespace
seperated list of capability names as
read by
<citerefentry><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
Capabilities listed will be included
in the bounding set, all others are
removed. If the list of capabilities
is prefixed with ~ all but the listed
capabilities will be included, the
effect of this assignment
inverted. Note that this option does
not actually set or unset any
capabilities in the effective,
permitted or inherited capability
sets. That's what
<varname>Capabilities=</varname> is
for. If this option is not used the
capability bounding set is not
modified on process execution, hence
no limits on the capabilities of the
process are enforced.</para></listitem>
</varlistentry>
<varlistentry>
@ -625,16 +646,21 @@
</varlistentry>
<varlistentry>
<term><varname>CapabilityBoundingSetDrop=</varname></term>
<term><varname>Capabilities=</varname></term>
<listitem><para>Controls the
capability bounding set drop set for
the executed process. See
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details. Takes a list of
capability names as read by
<citerefentry><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
set for the executed process. Take a
capability string describing the
effective, permitted and inherited
capability sets as documented in
<citerefentry><refentrytitle>cap_from_text</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
Note that these capability sets are
usually influenced by the capabilities
attached to the executed file. Due to
that
<varname>CapabilityBoundingSet=</varname>
is probably the much more useful
setting.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -221,7 +221,6 @@
processes of this mount shall be
killed. One of
<option>control-group</option>,
<option>process-group</option>,
<option>process</option>,
<option>none</option>.</para>

View File

@ -180,7 +180,7 @@
acquired. Service units with this
option configured implicitly gain
dependencies on the
<filename>dbus.target</filename>
<filename>dbus.socket</filename>
unit.</para>
<para>Behaviour of
@ -558,7 +558,6 @@
processes of this service shall be
killed. One of
<option>control-group</option>,
<option>process-group</option>,
<option>process</option>,
<option>none</option>.</para>
@ -570,10 +569,6 @@
stop command (as configured with
<varname>ExecStop=</varname>) is
executed. If set to
<option>process-group</option> only
the members of the process group of
the main service process are
killed. If set to
<option>process</option> only the main
process itself is killed. If set to
<option>none</option> no process is

View File

@ -519,7 +519,6 @@
processes of this socket unit shall be
killed. One of
<option>control-group</option>,
<option>process-group</option>,
<option>process</option>,
<option>none</option>.</para>

View File

@ -51,7 +51,6 @@
<para><filename>basic.target</filename>,
<filename>ctrl-alt-del.target</filename>,
<filename>dbus.service</filename>,
<filename>dbus.target</filename>,
<filename>default.target</filename>,
<filename>display-manager.service</filename>,
<filename>emergency.target</filename>,
@ -69,7 +68,7 @@
<filename>remote-fs.target</filename>,
<filename>rescue.target</filename>,
<filename>rpcbind.target</filename>,
<filename>rtc-set.target</filename>,
<filename>time-sync.target</filename>,
<filename>runlevel2.target</filename>,
<filename>runlevel3.target</filename>,
<filename>runlevel4.target</filename>,
@ -79,7 +78,6 @@
<filename>sockets.target</filename>,
<filename>swap.target</filename>,
<filename>sysinit.target</filename>,
<filename>@SPECIAL_SYSLOG_SERVICE@</filename>,
<filename>syslog.target</filename>,
<filename>systemd-initctl.service</filename>,
<filename>systemd-initctl.socket</filename>,
@ -143,28 +141,6 @@
up systemd will connect to it
and register its
service.</para>
<para>Units should generally
avoid depending on this unit
directly and instead refer to
the
<filename>dbus.target</filename>
unit instead, which pulls this
one in directly or indirectly
via socket-based activation.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>dbus.target</filename></term>
<listitem>
<para>Administrators should
ensure that this target pulls
in a service unit with the
name or alias of
<filename>dbus.service</filename>
(or a socket unit that
activates this
service).</para>
</listitem>
</varlistentry>
<varlistentry>
@ -180,7 +156,7 @@
<para>The default unit systemd
starts at bootup can be
overriden with the
<varname>systemd.default=</varname>
<varname>systemd.unit=</varname>
kernel command line option.</para>
</listitem>
</varlistentry>
@ -213,7 +189,7 @@
console. This unit is supposed
to be used with the kernel
command line option
<varname>systemd.default=</varname>
<varname>systemd.unit=</varname>
and has otherwise little use.
</para>
</listitem>
@ -423,7 +399,7 @@
</listitem>
</varlistentry>
<varlistentry>
<term><filename>rtc-set.target</filename></term>
<term><filename>time-sync.target</filename></term>
<listitem>
<para>systemd automatically
adds dependencies of type
@ -565,27 +541,6 @@
or b.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>@SPECIAL_SYSLOG_SERVICE@</filename></term>
<listitem>
<para>A special unit for the
syslog daemon. As soon as
this service is fully started
up systemd will connect to it
and use it for logging if it
has been configured for
that.</para>
<para>Units should generally
avoid depending on this unit
directly and instead refer to
the
<filename>syslog.target</filename>
unit instead, which pulls this
one in directly or indirectly
via socket-based activation.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>syslog.target</filename></term>
<listitem>
@ -597,15 +552,6 @@
referring to the
<literal>$syslog</literal>
facility.</para>
<para>Administrators should
ensure that this target pulls
in a service unit with the
name or alias of
<filename>@SPECIAL_SYSLOG_SERVICE@</filename>
(or a socket unit that
activates this
service).</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -68,13 +68,23 @@
specific configuration options are configured in the
[Swap] section.</para>
<para>Swap units must be named after the devices they
control. Example: the swap device
<para>Swap units must be named after the devices
(resp. files) they control. Example: the swap device
<filename>/dev/sda5</filename> must be configured in a
unit file <filename>dev-sda5.swap</filename>. For
details about the escaping logic used to convert a
file system path to a unit name see
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>All swap units automatically get the appropriate
dependencies on the devices (resp. on the mount points
of the files) they are actived from.</para>
<para>Swap units with
<varname>DefaultDependencies=</varname> enabled
implicitly acquire a conflicting dependency to
<filename>umount.target</filename> so that they are
deactivated at shutdown.</para>
</refsect1>
<refsect1>
@ -88,6 +98,13 @@
<para>If a swap device or file is configured in both
<filename>/etc/fstab</filename> and a unit file the
configuration in the latter takes precedence.</para>
<para>Unless the <option>noauto</option> option is set
for them all swap units configured in
<filename>/etc/fstab</filename> are also added as
requirements to <filename>swap.target</filename>, so
that they are waited for and activated during
boot.</para>
</refsect1>
<refsect1>
@ -149,7 +166,7 @@
a time span value such as "5min
20s". Pass 0 to disable the timeout
logic. Defaults to
60s.</para></listitem>
3min.</para></listitem>
</varlistentry>
<varlistentry>
@ -158,7 +175,6 @@
processes of this swap shall be
killed. One of
<option>control-group</option>,
<option>process-group</option>,
<option>process</option>,
<option>none</option>.</para>

View File

@ -83,14 +83,15 @@
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details).</para>
<para>Unless
<varname>DefaultDependencies=</varname> is set to
<option>false</option>, target units will
implicitly complement all configured dependencies of type
<varname>Wants=</varname>,
<para>Unless <varname>DefaultDependencies=</varname>
is set to <option>false</option>, target units will
implicitly complement all configured dependencies of
type <varname>Wants=</varname>,
<varname>Requires=</varname>,
<varname>RequiresOverridable=</varname> with
dependencies of type <varname>After=</varname>.
dependencies of type <varname>After=</varname> if the
units in question also have
<varname>DefaultDependencies=true</varname>.
</para>
</refsect1>

View File

@ -139,7 +139,10 @@
with the <command>enable</command> command of the
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
tool which reads information from the [Install]
section of unit files. (See below.)</para>
section of unit files. (See below.) A similar
functionality exists for <varname>Requires=</varname>
type dependencies as well, the directory suffix is
<filename>.requires/</filename> in this case.</para>
<para>Note that while systemd offers a flexible
dependency system between units it is recommended to
@ -216,21 +219,6 @@
dependent on the type of unit:</para>
<variablelist>
<varlistentry>
<term><varname>Names=</varname></term>
<listitem><para>Additional names for
this unit. The names listed here must
have the same suffix (i.e. type) as
the unit file name. This option may be
specified more than once, in which
case all listed names are used. Note
that this option is different from the
<varname>Alias=</varname> option from
the [Install] section mentioned
below. See below for details.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Description=</varname></term>
@ -573,9 +561,11 @@
<varlistentry>
<term><varname>ConditionPathExists=</varname></term>
<term><varname>ConditionPathIsDirectory=</varname></term>
<term><varname>ConditionDirectoryNotEmpty=</varname></term>
<term><varname>ConditionKernelCommandLine=</varname></term>
<term><varname>ConditionVirtualization=</varname></term>
<term><varname>ConditionSecurity=</varname></term>
<term><varname>ConditionNull=</varname></term>
<listitem><para>Before starting a unit
@ -596,10 +586,15 @@
is prefixed with an exclamation mark
(!), the test is negated, and the unit
only started if the path does not
exist. <varname>ConditionDirectoryNotEmpty=</varname>
exist. <varname>ConditionPathIsDirectory=</varname>
is similar to
<varname>ConditionPathExists=</varname>
but verifies whether a certain path is
but verifies whether a certain path
exists and is a directory.
<varname>ConditionDirectoryNotEmpty=</varname>
is similar to
<varname>ConditionPathExists=</varname>
but verifies whether a certain path
exists and is a non-empty
directory. Similarly
<varname>ConditionKernelCommandLine=</varname>
@ -630,9 +625,17 @@
<varname>microsoft</varname>,
<varname>oracle</varname>,
<varname>xen</varname>,
<varname>pidns</varname>,
<varname>openvz</varname> to test
against a specific implementation. The
test may be negated by prepending an
exclamation mark.
<varname>ConditionSecurity=</varname>
may be used to check whether the given security
module is enabled on the system.
Currently the only recognized value is
<varname>selinux</varname>.
The test may be negated by prepending an
exclamation mark. Finally,
<varname>ConditionNull=</varname> may
be used to add a constant condition
@ -657,6 +660,35 @@
pipe symbol must be passed first, the
exclamation second.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Names=</varname></term>
<listitem><para>Additional names for
this unit. The names listed here must
have the same suffix (i.e. type) as
the unit file name. This option may be
specified more than once, in which
case all listed names are used. Note
that this option is different from the
<varname>Alias=</varname> option from
the [Install] section mentioned
below. See below for details. Note
that in almost all cases this option
is not what you want. A symlink alias
in the file system is generally
preferable since it can be used as
lookup key. If a unit with a symlinked
alias name is not loaded and needs to
be it is easily found via the
symlink. However, if a unit with an
alias name configured with this
setting is not loaded it will not be
discovered. This settings' only use is
in conjunction with service
instances.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Unit file may include a [Install] section, which

View File

@ -269,7 +269,7 @@
<option>syslog</option>,
<option>syslog+console</option>,
<option>kmsg</option>,
<option>kmsg-console</option>. If the
<option>kmsg+console</option>. If the
argument is omitted it defaults to
<option>inherit</option>.</para></listitem>
</varlistentry>
@ -1024,20 +1024,19 @@
<variablelist>
<varlistentry>
<term><filename>@/org/freedesktop/systemd1/notify</filename></term>
<term><filename>/run/systemd/notify</filename></term>
<listitem><para>Daemon status
notification socket. This is an AF_UNIX
datagram socket in the Linux abstract
namespace, and is used to implement
the daemon notification logic as
implemented by
notification socket. This is an
AF_UNIX datagram socket and is used to
implement the daemon notification
logic as implemented by
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>@/org/freedesktop/systemd1/logger</filename></term>
<term><filename>/run/systemd/logger</filename></term>
<listitem><para>Used internally by the
<filename>systemd-logger.service</filename>
@ -1045,32 +1044,30 @@
of spawned processes to
<citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
or the kernel log buffer. This is an
AF_UNIX stream socket in the Linux
abstract namespace.</para></listitem>
AF_UNIX stream
socket.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>@/org/freedesktop/systemd1/shutdown</filename></term>
<term><filename>/run/systemd/shutdownd</filename></term>
<listitem><para>Used internally by the
<citerefentry><refentrytitle>shutdown</refentrytitle><manvolnum>8</manvolnum></citerefentry>
tool to implement delayed
shutdowns. This is an AF_UNIX datagram
socket in the Linux abstract
namespace.</para></listitem>
socket.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>@/org/freedesktop/systemd1/private</filename></term>
<term><filename>/run/systemd/private</filename></term>
<listitem><para>Used internally as
communication channel between
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
and the systemd process. This is an
AF_UNIX stream socket in the Linux
abstract namespace. This interface is
private to systemd and should not be
used in external
AF_UNIX stream socket. This interface
is private to systemd and should not
be used in external
projects.</para></listitem>
</varlistentry>

View File

@ -58,7 +58,7 @@
<filename>/etc/tmpfiles.d/</filename> to describe the
creation, cleaning and removal of volatile and
temporary files and directories which usually reside
in directories such as <filename>/var/run</filename>
in directories such as <filename>/run</filename>
or <filename>/tmp</filename>. Each configuration file
is named in the style of
<filename>/etc/tmpfiles.d/&lt;program&gt;.conf</filename>.</para>
@ -72,7 +72,7 @@
fields:</para>
<programlisting>Type Path Mode UID GID Age
d /var/run/user 0755 root root 10d</programlisting>
d /run/user 0755 root root 10d</programlisting>
<refsect2>
<title>Type</title>

1
src/.gitignore vendored
View File

@ -1,3 +1,4 @@
org.freedesktop.systemd1.policy
gnome-ask-password-agent.c
systemd-interfaces.c
systemadm.c

View File

@ -8,9 +8,7 @@
ACTION!="add|change", GOTO="systemd_end"
SUBSYSTEM=="tty", KERNEL=="tty[0-9]|tty1[0-2]", TAG+="systemd"
SUBSYSTEM=="tty", KERNEL=="ttyS*", TAG+="systemd"
SUBSYSTEM=="tty", KERNEL=="hvc*", TAG+="systemd"
SUBSYSTEM=="tty", KERNEL=="ttyUSB*", TAG+="systemd"
SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*", TAG+="systemd"
SUBSYSTEM=="block", KERNEL!="ram*|loop*", TAG+="systemd"
SUBSYSTEM=="block", KERNEL!="ram*|loop*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"

View File

@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
#include <termios.h>
#include <unistd.h>
#include <sys/poll.h>
@ -36,6 +36,18 @@
#include "ask-password-api.h"
static void backspace_chars(int ttyfd, size_t p) {
if (ttyfd < 0)
return;
while (p > 0) {
p--;
loop_write(ttyfd, "\b \b", 3, false);
}
}
int ask_password_tty(
const char *message,
usec_t until,
@ -48,6 +60,8 @@ int ask_password_tty(
int r, ttyfd = -1, notify = -1;
struct pollfd pollfd[2];
bool reset_tty = false;
bool silent_mode = false;
bool dirty = false;
enum {
POLL_TTY,
POLL_INOTIFY
@ -155,27 +169,50 @@ int ask_password_tty(
if (c == '\n')
break;
else if (c == 21) {
else if (c == 21) { /* C-u */
while (p > 0) {
p--;
if (ttyfd >= 0)
loop_write(ttyfd, "\b \b", 3, false);
}
if (!silent_mode)
backspace_chars(ttyfd, p);
p = 0;
} else if (c == '\b' || c == 127) {
if (p > 0) {
p--;
if (p > 0) {
if (!silent_mode)
backspace_chars(ttyfd, 1);
p--;
} else if (!dirty && !silent_mode) {
silent_mode = true;
/* There are two ways to enter silent
* mode. Either by pressing backspace
* as first key (and only as first key),
* or ... */
if (ttyfd >= 0)
loop_write(ttyfd, "\b \b", 3, false);
}
loop_write(ttyfd, "(no echo) ", 10, false);
} else if (ttyfd >= 0)
loop_write(ttyfd, "\a", 1, false);
} else if (c == '\t' && !silent_mode) {
backspace_chars(ttyfd, p);
silent_mode = true;
/* ... or by pressing TAB at any time. */
if (ttyfd >= 0)
loop_write(ttyfd, "(no echo) ", 10, false);
} else {
passphrase[p++] = c;
if (ttyfd >= 0)
if (!silent_mode && ttyfd >= 0)
loop_write(ttyfd, "*", 1, false);
dirty = true;
}
}
@ -223,7 +260,7 @@ static int create_socket(char **name) {
zero(sa);
sa.un.sun_family = AF_UNIX;
snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/dev/.systemd/ask-password/sck.%llu", random_ull());
snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%llu", random_ull());
if (bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
r = -errno;
@ -265,18 +302,22 @@ int ask_password_agent(
_FD_MAX
};
char temp[] = "/dev/.systemd/ask-password/tmp.XXXXXX";
char temp[] = "/run/systemd/ask-password/tmp.XXXXXX";
char final[sizeof(temp)] = "";
int fd = -1, r;
FILE *f = NULL;
char *socket_name = NULL;
int socket_fd = -1, signal_fd = -1;
sigset_t mask;
sigset_t mask, oldmask;
struct pollfd pollfd[_FD_MAX];
assert(_passphrases);
mkdir_p("/dev/.systemd/ask-password", 0755);
assert_se(sigemptyset(&mask) == 0);
sigset_add_many(&mask, SIGINT, SIGTERM, -1);
assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
mkdir_p("/run/systemd/ask-password", 0755);
if ((fd = mkostemp(temp, O_CLOEXEC|O_CREAT|O_WRONLY)) < 0) {
log_error("Failed to create password file: %m");
@ -294,10 +335,6 @@ int ask_password_agent(
fd = -1;
assert_se(sigemptyset(&mask) == 0);
sigset_add_many(&mask, SIGINT, SIGTERM, -1);
assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
if ((signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
log_error("signalfd(): %m");
r = -errno;
@ -493,6 +530,8 @@ finish:
if (final[0])
unlink(final);
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
return r;
}

187
src/binfmt.c Normal file
View File

@ -0,0 +1,187 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include "log.h"
#include "util.h"
static int delete_rule(const char *rule) {
char *x, *fn, *e;
int r;
assert(rule[0]);
if (!(x = strdup(rule)))
return -ENOMEM;
e = strchrnul(x+1, x[0]);
*e = 0;
asprintf(&fn, "/proc/sys/fs/binfmt_misc/%s", x+1);
free(x);
if (!fn)
return -ENOMEM;
r = write_one_line_file(fn, "-1");
free(fn);
return r;
}
static int apply_rule(const char *rule) {
int r;
delete_rule(rule);
if ((r = write_one_line_file("/proc/sys/fs/binfmt_misc/register", rule)) < 0) {
log_error("Failed to add binary format: %s", strerror(-r));
return r;
}
return 0;
}
static int apply_file(const char *path, bool ignore_enoent) {
FILE *f;
int r = 0;
assert(path);
if (!(f = fopen(path, "re"))) {
if (ignore_enoent && errno == ENOENT)
return 0;
log_error("Failed to open file '%s', ignoring: %m", path);
return -errno;
}
while (!feof(f)) {
char l[LINE_MAX], *p;
int k;
if (!fgets(l, sizeof(l), f)) {
if (feof(f))
break;
log_error("Failed to read file '%s', ignoring: %m", path);
r = -errno;
goto finish;
}
p = strstrip(l);
if (!*p)
continue;
if (strchr(COMMENTS, *p))
continue;
if ((k = apply_rule(p)) < 0 && r == 0)
r = k;
}
finish:
fclose(f);
return r;
}
static int scandir_filter(const struct dirent *d) {
assert(d);
if (ignore_file(d->d_name))
return 0;
if (d->d_type != DT_REG &&
d->d_type != DT_LNK &&
d->d_type != DT_UNKNOWN)
return 0;
return endswith(d->d_name, ".conf");
}
static int apply_tree(const char *path) {
struct dirent **de = NULL;
int n, i, r = 0;
if ((n = scandir(path, &de, scandir_filter, alphasort)) < 0) {
if (errno == ENOENT)
return 0;
log_error("Failed to enumerate %s files: %m", path);
return -errno;
}
for (i = 0; i < n; i++) {
char *fn;
int k;
k = asprintf(&fn, "%s/%s", path, de[i]->d_name);
free(de[i]);
if (k < 0) {
log_error("Failed to allocate file name.");
if (r == 0)
r = -ENOMEM;
continue;
}
if ((k = apply_file(fn, true)) < 0 && r == 0)
r = k;
}
free(de);
return r;
}
int main(int argc, char *argv[]) {
int r = 0;
if (argc > 2) {
log_error("This program expects one or no arguments.");
return EXIT_FAILURE;
}
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
if (argc > 1)
r = apply_file(argv[1], false);
else {
/* Flush out all rules */
write_one_line_file("/proc/sys/fs/binfmt_misc/status", "-1");
r = apply_tree("/etc/binfmt.d");
}
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

367
src/bridge.c Normal file
View File

@ -0,0 +1,367 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/epoll.h>
#include <stddef.h>
#include "log.h"
#include "util.h"
#include "socket-util.h"
#define BUFFER_SIZE (64*1024)
#define EXTRA_SIZE 16
static bool initial_nul = false;
static bool auth_over = false;
static void format_uid(char *buf, size_t l) {
char text[20 + 1]; /* enough space for a 64bit integer plus NUL */
unsigned j;
assert(l > 0);
snprintf(text, sizeof(text)-1, "%llu", (unsigned long long) geteuid());
text[sizeof(text)-1] = 0;
memset(buf, 0, l);
for (j = 0; text[j] && j*2+2 < l; j++) {
buf[j*2] = hexchar(text[j] >> 4);
buf[j*2+1] = hexchar(text[j] & 0xF);
}
buf[j*2] = 0;
}
static size_t patch_in_line(char *line, size_t l, size_t left) {
size_t r;
if (line[0] == 0 && !initial_nul) {
initial_nul = true;
line += 1;
l -= 1;
r = 1;
} else
r = 0;
if (l == 5 && strncmp(line, "BEGIN", 5) == 0) {
r += l;
auth_over = true;
} else if (l == 17 && strncmp(line, "NEGOTIATE_UNIX_FD", 17) == 0) {
memmove(line + 13, line + 17, left);
memcpy(line, "NEGOTIATE_NOP", 13);
r += 13;
} else if (l >= 14 && strncmp(line, "AUTH EXTERNAL ", 14) == 0) {
char uid[20*2 + 1];
size_t len;
format_uid(uid, sizeof(uid));
len = strlen(uid);
assert(len <= EXTRA_SIZE);
memmove(line + 14 + len, line + l, left);
memcpy(line + 14, uid, len);
r += 14 + len;
} else
r += l;
return r;
}
static size_t patch_in_buffer(char* in_buffer, size_t *in_buffer_full) {
size_t i, good = 0;
if (*in_buffer_full <= 0)
return *in_buffer_full;
/* If authentication is done, we don't touch anything anymore */
if (auth_over)
return *in_buffer_full;
if (*in_buffer_full < 2)
return 0;
for (i = 0; i <= *in_buffer_full - 2; i ++) {
/* Fully lines can be send on */
if (in_buffer[i] == '\r' && in_buffer[i+1] == '\n') {
if (i > good) {
size_t old_length, new_length;
old_length = i - good;
new_length = patch_in_line(in_buffer+good, old_length, *in_buffer_full - i);
*in_buffer_full = *in_buffer_full + new_length - old_length;
good += new_length + 2;
} else
good = i+2;
}
if (auth_over)
break;
}
return good;
}
int main(int argc, char *argv[]) {
int r = EXIT_FAILURE, fd = -1, ep = -1;
union sockaddr_union sa;
char in_buffer[BUFFER_SIZE+EXTRA_SIZE], out_buffer[BUFFER_SIZE+EXTRA_SIZE];
size_t in_buffer_full = 0, out_buffer_full = 0;
struct epoll_event stdin_ev, stdout_ev, fd_ev;
bool stdin_readable = false, stdout_writable = false, fd_readable = false, fd_writable = false;
bool stdin_rhup = false, stdout_whup = false, fd_rhup = false, fd_whup = false;
if (argc > 1) {
log_error("This program takes no argument.");
return EXIT_FAILURE;
}
log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
log_parse_environment();
log_open();
if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
log_error("Failed to create socket: %s", strerror(errno));
goto finish;
}
zero(sa);
sa.un.sun_family = AF_UNIX;
strncpy(sa.un.sun_path, "/run/dbus/system_bus_socket", sizeof(sa.un.sun_path));
if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
log_error("Failed to connect: %m");
goto finish;
}
fd_nonblock(STDIN_FILENO, 1);
fd_nonblock(STDOUT_FILENO, 1);
if ((ep = epoll_create1(EPOLL_CLOEXEC)) < 0) {
log_error("Failed to create epoll: %m");
goto finish;
}
zero(stdin_ev);
stdin_ev.events = EPOLLIN|EPOLLET;
stdin_ev.data.fd = STDIN_FILENO;
zero(stdout_ev);
stdout_ev.events = EPOLLOUT|EPOLLET;
stdout_ev.data.fd = STDOUT_FILENO;
zero(fd_ev);
fd_ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
fd_ev.data.fd = fd;
if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev) < 0 ||
epoll_ctl(ep, EPOLL_CTL_ADD, STDOUT_FILENO, &stdout_ev) < 0 ||
epoll_ctl(ep, EPOLL_CTL_ADD, fd, &fd_ev) < 0) {
log_error("Failed to regiser fds in epoll: %m");
goto finish;
}
do {
struct epoll_event ev[16];
ssize_t k;
int i, nfds;
if ((nfds = epoll_wait(ep, ev, ELEMENTSOF(ev), -1)) < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
log_error("epoll_wait(): %m");
goto finish;
}
assert(nfds >= 1);
for (i = 0; i < nfds; i++) {
if (ev[i].data.fd == STDIN_FILENO) {
if (!stdin_rhup && (ev[i].events & (EPOLLHUP|EPOLLIN)))
stdin_readable = true;
} else if (ev[i].data.fd == STDOUT_FILENO) {
if (ev[i].events & EPOLLHUP) {
stdout_writable = false;
stdout_whup = true;
}
if (!stdout_whup && (ev[i].events & EPOLLOUT))
stdout_writable = true;
} else if (ev[i].data.fd == fd) {
if (ev[i].events & EPOLLHUP) {
fd_writable = false;
fd_whup = true;
}
if (!fd_rhup && (ev[i].events & (EPOLLHUP|EPOLLIN)))
fd_readable = true;
if (!fd_whup && (ev[i].events & EPOLLOUT))
fd_writable = true;
}
}
while ((stdin_readable && in_buffer_full <= 0) ||
(fd_writable && patch_in_buffer(in_buffer, &in_buffer_full) > 0) ||
(fd_readable && out_buffer_full <= 0) ||
(stdout_writable && out_buffer_full > 0)) {
size_t in_buffer_good = 0;
if (stdin_readable && in_buffer_full < BUFFER_SIZE) {
if ((k = read(STDIN_FILENO, in_buffer + in_buffer_full, BUFFER_SIZE - in_buffer_full)) < 0) {
if (errno == EAGAIN)
stdin_readable = false;
else if (errno == EPIPE || errno == ECONNRESET)
k = 0;
else {
log_error("read(): %m");
goto finish;
}
} else
in_buffer_full += (size_t) k;
if (k == 0) {
stdin_rhup = true;
stdin_readable = false;
shutdown(STDIN_FILENO, SHUT_RD);
close_nointr_nofail(STDIN_FILENO);
}
}
in_buffer_good = patch_in_buffer(in_buffer, &in_buffer_full);
if (fd_writable && in_buffer_good > 0) {
if ((k = write(fd, in_buffer, in_buffer_good)) < 0) {
if (errno == EAGAIN)
fd_writable = false;
else if (errno == EPIPE || errno == ECONNRESET) {
fd_whup = true;
fd_writable = false;
shutdown(fd, SHUT_WR);
} else {
log_error("write(): %m");
goto finish;
}
} else {
assert(in_buffer_full >= (size_t) k);
memmove(in_buffer, in_buffer + k, in_buffer_full - k);
in_buffer_full -= k;
}
}
if (fd_readable && out_buffer_full < BUFFER_SIZE) {
if ((k = read(fd, out_buffer + out_buffer_full, BUFFER_SIZE - out_buffer_full)) < 0) {
if (errno == EAGAIN)
fd_readable = false;
else if (errno == EPIPE || errno == ECONNRESET)
k = 0;
else {
log_error("read(): %m");
goto finish;
}
} else
out_buffer_full += (size_t) k;
if (k == 0) {
fd_rhup = true;
fd_readable = false;
shutdown(fd, SHUT_RD);
}
}
if (stdout_writable && out_buffer_full > 0) {
if ((k = write(STDOUT_FILENO, out_buffer, out_buffer_full)) < 0) {
if (errno == EAGAIN)
stdout_writable = false;
else if (errno == EPIPE || errno == ECONNRESET) {
stdout_whup = true;
stdout_writable = false;
shutdown(STDOUT_FILENO, SHUT_WR);
close_nointr(STDOUT_FILENO);
} else {
log_error("write(): %m");
goto finish;
}
} else {
assert(out_buffer_full >= (size_t) k);
memmove(out_buffer, out_buffer + k, out_buffer_full - k);
out_buffer_full -= k;
}
}
}
if (stdin_rhup && in_buffer_full <= 0 && !fd_whup) {
fd_whup = true;
fd_writable = false;
shutdown(fd, SHUT_WR);
}
if (fd_rhup && out_buffer_full <= 0 && !stdout_whup) {
stdout_whup = true;
stdout_writable = false;
shutdown(STDOUT_FILENO, SHUT_WR);
close_nointr(STDOUT_FILENO);
}
} while (!stdout_whup || !fd_whup);
r = EXIT_SUCCESS;
finish:
if (fd >= 0)
close_nointr_nofail(fd);
if (ep >= 0)
close_nointr_nofail(ep);
return r;
}

View File

@ -106,8 +106,22 @@ int main(int argc, char *argv[]) {
if (path_startswith(p, "/sys/fs/cgroup")) {
printf("Working Directory %s:\n", p);
r = show_cgroup_by_path(p, NULL, 0);
} else
r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, "/", NULL, 0);
} else {
char *root = NULL;
const char *t = NULL;
if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root)) < 0)
t = "/";
else {
if (endswith(root, "/system"))
root[strlen(root)-7] = 0;
t = root[0] ? root : "/";
}
r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, t, NULL, 0);
free(root);
}
free(p);
}

View File

@ -484,6 +484,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
const char *p;
char *mp;
int r;
static __thread bool good = false;
assert(controller);
assert(fs);
@ -504,9 +505,14 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
if (asprintf(&mp, "/sys/fs/cgroup/%s", p) < 0)
return -ENOMEM;
if ((r = path_is_mount_point(mp)) <= 0) {
free(mp);
return r < 0 ? r : -ENOENT;
if (!good) {
if ((r = path_is_mount_point(mp)) <= 0) {
free(mp);
return r < 0 ? r : -ENOENT;
}
/* Cache this to save a few stat()s */
good = true;
}
if (path && suffix)
@ -967,3 +973,31 @@ int cg_fix_path(const char *path, char **result) {
return r;
}
int cg_get_user_path(char **path) {
char *root, *p;
assert(path);
/* Figure out the place to put user cgroups below. We use the
* same as PID 1 has but with the "/system" suffix replaced by
* "/user" */
if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0)
p = strdup("/user");
else {
if (endswith(root, "/system"))
root[strlen(root) - 7] = 0;
else if (streq(root, "/"))
root[0] = 0;
p = strappend(root, "/user");
free(root);
}
if (!p)
return -ENOMEM;
*path = p;
return 0;
}

View File

@ -27,8 +27,7 @@
#include <dirent.h>
#include "set.h"
#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
#include "def.h"
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f);
@ -68,4 +67,6 @@ int cg_install_release_agent(const char *controller, const char *agent);
int cg_is_empty(const char *controller, const char *path, bool ignore_self);
int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self);
int cg_get_user_path(char **path);
#endif

View File

@ -226,8 +226,10 @@ int manager_setup_cgroup(Manager *m) {
assert(m);
/* 1. Determine hierarchy */
if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current)) < 0)
if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current)) < 0) {
log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
goto finish;
}
if (m->running_as == MANAGER_SYSTEM)
strcpy(suffix, "/system");
@ -246,14 +248,17 @@ int manager_setup_cgroup(Manager *m) {
/* We need a new root cgroup */
m->cgroup_hierarchy = NULL;
if (asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix) < 0) {
log_error("Out of memory");
r = -ENOMEM;
goto finish;
}
}
/* 2. Show data */
if ((r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path)) < 0)
if ((r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path)) < 0) {
log_error("Cannot find cgroup mount point: %s", strerror(-r));
goto finish;
}
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
@ -276,6 +281,7 @@ int manager_setup_cgroup(Manager *m) {
close_nointr_nofail(m->pin_cgroupfs_fd);
if ((m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK)) < 0) {
log_error("Failed to open pin file: %m");
r = -errno;
goto finish;
}

View File

@ -49,10 +49,19 @@ int main(int argc, char *argv[]) {
* this to avoid an activation loop when we start dbus when we
* are called when the dbus service is shut down. */
if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", &error))) {
log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
goto finish;
if (!(bus = dbus_connection_open_private("unix:path=/run/systemd/private", &error))) {
#ifndef LEGACY
dbus_error_free(&error);
/* Retry with the pre v21 socket name, to ease upgrades */
if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", &error))) {
#endif
log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
goto finish;
}
#ifndef LEGACY
}
#endif
if (bus_check_peercred(bus) < 0) {
log_error("Bus owner not root.");

View File

@ -24,13 +24,19 @@
#include <string.h>
#include <unistd.h>
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#endif
#include "util.h"
#include "condition.h"
Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
Condition *c;
c = new0(Condition, 1);
if (!(c = new0(Condition, 1)))
return NULL;
c->type = type;
c->trigger = trigger;
c->negate = negate;
@ -67,6 +73,9 @@ static bool test_kernel_command_line(const char *parameter) {
assert(parameter);
if (detect_virtualization(NULL) > 0)
return false;
if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
return false;
@ -123,6 +132,14 @@ static bool test_virtualization(const char *parameter) {
return streq(parameter, id);
}
static bool test_security(const char *parameter) {
#ifdef HAVE_SELINUX
if (streq(parameter, "selinux"))
return is_selinux_enabled() > 0;
#endif
return false;
}
bool condition_test(Condition *c) {
assert(c);
@ -131,6 +148,14 @@ bool condition_test(Condition *c) {
case CONDITION_PATH_EXISTS:
return (access(c->parameter, F_OK) >= 0) == !c->negate;
case CONDITION_PATH_IS_DIRECTORY: {
struct stat st;
if (lstat(c->parameter, &st) < 0)
return !c->negate;
return S_ISDIR(st.st_mode) == !c->negate;
}
case CONDITION_DIRECTORY_NOT_EMPTY: {
int k;
@ -144,6 +169,9 @@ bool condition_test(Condition *c) {
case CONDITION_VIRTUALIZATION:
return test_virtualization(c->parameter) == !c->negate;
case CONDITION_SECURITY:
return test_security(c->parameter) == !c->negate;
case CONDITION_NULL:
return !c->negate;
@ -186,7 +214,7 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
prefix = "";
fprintf(f,
"%s%s: %s%s%s\n",
"%s\t%s: %s%s%s\n",
prefix,
condition_type_to_string(c->type),
c->trigger ? "|" : "",
@ -202,8 +230,12 @@ void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
}
static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
[CONDITION_PATH_EXISTS] = "ConditionPathExists",
[CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
[CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
[CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
[CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
[CONDITION_SECURITY] = "ConditionSecurity",
[CONDITION_NULL] = "ConditionNull"
};

View File

@ -28,9 +28,11 @@
typedef enum ConditionType {
CONDITION_PATH_EXISTS,
CONDITION_PATH_IS_DIRECTORY,
CONDITION_DIRECTORY_NOT_EMPTY,
CONDITION_KERNEL_COMMAND_LINE,
CONDITION_VIRTUALIZATION,
CONDITION_SECURITY,
CONDITION_NULL,
_CONDITION_TYPE_MAX,
_CONDITION_TYPE_INVALID = -1

View File

@ -61,7 +61,7 @@ static int next_assignment(
if (!t->parse)
return 0;
return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata);
return t->parse(filename, line, section, lvalue, t->ltype, rvalue, t->data, userdata);
}
/* Warn about unknown non-extension fields. */
@ -226,6 +226,7 @@ int config_parse_int(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -251,6 +252,7 @@ int config_parse_uint64(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -276,6 +278,7 @@ int config_parse_unsigned(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -301,6 +304,7 @@ int config_parse_size(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -328,6 +332,7 @@ int config_parse_bool(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -354,6 +359,7 @@ int config_parse_string(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -383,6 +389,7 @@ int config_parse_path(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -416,6 +423,7 @@ int config_parse_strv(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -468,6 +476,7 @@ int config_parse_path_strv(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {

View File

@ -28,12 +28,13 @@
/* An abstract parser for simple, line based, shallow configuration
* files consisting of variable assignments only. */
typedef int (*ConfigParserCallback)(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
typedef int (*ConfigParserCallback)(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
/* Wraps info for parsing a specific configuration variable */
typedef struct ConfigItem {
const char *lvalue; /* name of the variable */
ConfigParserCallback parse; /* Function that is called to parse the variable's value */
int ltype; /* Distinguish differnt variables passed to the same callback */
void *data; /* Where to store the variable's data */
const char *section;
} ConfigItem;
@ -44,15 +45,15 @@ typedef struct ConfigItem {
int config_parse(const char *filename, FILE *f, const char* const *sections, const ConfigItem *t, bool relaxed, void *userdata);
/* Generic parsers */
int config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_uint64(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_path(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_strv(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_path_strv(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
int config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_uint64(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_path_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
int function( \
@ -60,6 +61,7 @@ int config_parse_path_strv(const char *filename, unsigned line, const char *sect
unsigned line, \
const char *section, \
const char *lvalue, \
int ltype, \
const char *rvalue, \
void *data, \
void *userdata) { \

View File

@ -222,7 +222,8 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
arg_dest = argv[1];
if (argc > 1)
arg_dest = argv[1];
log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
log_parse_environment();

View File

@ -31,6 +31,7 @@
#include "util.h"
#include "strv.h"
#include "ask-password-api.h"
#include "def.h"
static const char *opt_type = NULL; /* LUKS1 or PLAIN */
static char *opt_cipher = NULL;
@ -308,7 +309,7 @@ int main(int argc, char *argv[]) {
if (opt_readonly)
flags |= CRYPT_ACTIVATE_READONLY;
until = now(CLOCK_MONOTONIC) + (opt_timeout > 0 ? opt_timeout : 60 * USEC_PER_SEC);
until = now(CLOCK_MONOTONIC) + (opt_timeout > 0 ? opt_timeout : DEFAULT_TIMEOUT_USEC);
opt_tries = opt_tries > 0 ? opt_tries : 3;
opt_key_size = (opt_key_size > 0 ? opt_key_size : 256);

View File

@ -38,6 +38,10 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Automount\0"
const char bus_automount_interface[] _introspect_("Automount") = BUS_AUTOMOUNT_INTERFACE;
DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
@ -48,5 +52,5 @@ DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBus
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -23,10 +23,14 @@
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dbus/dbus.h>
#include "log.h"
#include "dbus-common.h"
#include "util.h"
#include "def.h"
int bus_check_peercred(DBusConnection *c) {
int fd;
@ -54,18 +58,66 @@ int bus_check_peercred(DBusConnection *c) {
return 1;
}
static int sync_auth(DBusConnection *bus, DBusError *error) {
usec_t begin, tstamp;
assert(bus);
/* This complexity should probably move into D-Bus itself:
*
* https://bugs.freedesktop.org/show_bug.cgi?id=35189 */
begin = tstamp = now(CLOCK_MONOTONIC);
for (;;) {
if (tstamp > begin + DEFAULT_TIMEOUT_USEC)
break;
if (dbus_connection_get_is_authenticated(bus))
break;
if (!dbus_connection_read_write_dispatch(bus, ((begin + DEFAULT_TIMEOUT_USEC - tstamp) + USEC_PER_MSEC - 1) / USEC_PER_MSEC))
break;
tstamp = now(CLOCK_MONOTONIC);
}
if (!dbus_connection_get_is_connected(bus)) {
dbus_set_error_const(error, DBUS_ERROR_NO_SERVER, "Connection terminated during authentication.");
return -ECONNREFUSED;
}
if (!dbus_connection_get_is_authenticated(bus)) {
dbus_set_error_const(error, DBUS_ERROR_TIMEOUT, "Failed to authenticate in time.");
return -EACCES;
}
return 0;
}
int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private, DBusError *error) {
DBusConnection *bus;
int r;
assert(_bus);
/* If we are root, then let's not go via the bus */
if (geteuid() == 0 && t == DBUS_BUS_SYSTEM) {
if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", error)))
return -EIO;
if (!(bus = dbus_connection_open_private("unix:path=/run/systemd/private", error))) {
#ifndef LEGACY
dbus_error_free(error);
/* Retry with the pre v21 socket name, to ease upgrades */
if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", error)))
#endif
return -EIO;
}
dbus_connection_set_exit_on_disconnect(bus, FALSE);
if (bus_check_peercred(bus) < 0) {
dbus_connection_close(bus);
dbus_connection_unref(bus);
dbus_set_error_const(error, DBUS_ERROR_ACCESS_DENIED, "Failed to verify owner of bus.");
@ -79,12 +131,93 @@ int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private, DBusError *
if (!(bus = dbus_bus_get_private(t, error)))
return -EIO;
dbus_connection_set_exit_on_disconnect(bus, FALSE);
if (private)
*private = false;
}
if ((r = sync_auth(bus, error)) < 0) {
dbus_connection_close(bus);
dbus_connection_unref(bus);
return r;
}
*_bus = bus;
return 0;
}
int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error) {
DBusConnection *bus;
char *p = NULL;
int r;
assert(_bus);
assert(user || host);
if (user && host)
asprintf(&p, "exec:path=ssh,argv1=-xT,argv2=%s@%s,argv3=systemd-stdio-bridge", user, host);
else if (user)
asprintf(&p, "exec:path=ssh,argv1=-xT,argv2=%s@localhost,argv3=systemd-stdio-bridge", user);
else if (host)
asprintf(&p, "exec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
if (!p) {
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
return -ENOMEM;
}
bus = dbus_connection_open_private(p, error);
free(p);
if (!bus)
return -EIO;
dbus_connection_set_exit_on_disconnect(bus, FALSE);
if ((r = sync_auth(bus, error)) < 0) {
dbus_connection_close(bus);
dbus_connection_unref(bus);
return r;
}
if (!dbus_bus_register(bus, error)) {
dbus_connection_close(bus);
dbus_connection_unref(bus);
return r;
}
*_bus = bus;
return 0;
}
int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error) {
DBusConnection *bus;
int r;
assert(_bus);
/* Don't bother with PolicyKit if we are root */
if (geteuid() == 0)
return bus_connect(DBUS_BUS_SYSTEM, _bus, NULL, error);
if (!(bus = dbus_connection_open_private("exec:path=pkexec,argv1=" SYSTEMD_STDIO_BRIDGE_BINARY_PATH, error)))
return -EIO;
dbus_connection_set_exit_on_disconnect(bus, FALSE);
if ((r = sync_auth(bus, error)) < 0) {
dbus_connection_close(bus);
dbus_connection_unref(bus);
return r;
}
if (!dbus_bus_register(bus, error)) {
dbus_connection_close(bus);
dbus_connection_unref(bus);
return r;
}
*_bus = bus;
return 0;
}

View File

@ -28,6 +28,9 @@ int bus_check_peercred(DBusConnection *c);
int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private_bus, DBusError *error);
int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error);
int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error);
const char *bus_error_message(const DBusError *error);
#endif

View File

@ -37,11 +37,14 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Device\0"
const char bus_device_interface[] _introspect_("Device") = BUS_DEVICE_INTERFACE;
const char bus_device_invalidating_properties[] =
"SysFSPath\0"
"\0";
"SysFSPath\0";
DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
const BusProperty properties[] = {
@ -50,5 +53,5 @@ DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMes
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -234,6 +234,24 @@ int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const ch
return 0;
}
int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
uint64_t normal, inverted;
assert(m);
assert(i);
assert(property);
assert(c);
/* We store this negated internally, to match the kernel, bu
* we expose it normalized. */
normal = *(uint64_t*) data;
inverted = ~normal;
return bus_property_append_uint64(m, i, property, &inverted);
}
int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
char *t = NULL;

View File

@ -131,7 +131,7 @@
{ interface, "SyslogLevelPrefix", bus_property_append_bool, "b", &(context).syslog_level_prefix }, \
{ interface, "Capabilities", bus_execute_append_capabilities, "s",&(context) }, \
{ interface, "SecureBits", bus_property_append_int, "i", &(context).secure_bits }, \
{ interface, "CapabilityBoundingSetDrop", bus_property_append_uint64, "t", &(context).capability_bounding_set_drop }, \
{ interface, "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", &(context).capability_bounding_set_drop }, \
{ interface, "User", bus_property_append_string, "s", (context).user }, \
{ interface, "Group", bus_property_append_string, "s", (context).group }, \
{ interface, "SupplementaryGroups", bus_property_append_strv, "as", (context).supplementary_groups }, \
@ -167,6 +167,7 @@ int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const
int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_command(Manager *m, DBusMessageIter *u, const char *property, void *data);
int bus_execute_append_kill_mode(Manager *m, DBusMessageIter *i, const char *property, void *data);

View File

@ -45,9 +45,12 @@
const char bus_job_interface[] _introspect_("Job") = BUS_JOB_INTERFACE;
#define INTERFACES_LIST \
BUS_GENERIC_INTERFACES_LIST \
"org.freedesktop.systemd1.Job\0"
#define INVALIDATING_PROPERTIES \
"State\0" \
"\0" \
"State\0"
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_state, job_state, JobState);
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_type, job_type, JobType);
@ -100,7 +103,7 @@ static DBusHandlerResult bus_job_message_dispatch(Job *j, DBusConnection *connec
job_finish_and_invalidate(j, JOB_CANCELED);
} else
return bus_default_message_handler(j->manager, connection, message, INTROSPECTION, properties);
return bus_default_message_handler(j->manager, connection, message, INTROSPECTION, INTERFACES_LIST, properties);
if (reply) {
if (!dbus_connection_send(connection, reply, NULL))
@ -195,6 +198,8 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu
if (r == -ENOENT) {
DBusError e;
dbus_error_init(&e);
dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown job");
return bus_send_error_reply(m, connection, message, &e, r);
}

View File

@ -20,6 +20,7 @@
***/
#include <errno.h>
#include <unistd.h>
#include "dbus.h"
#include "log.h"
@ -206,6 +207,10 @@
#define INTROSPECTION_END \
"</node>\n"
#define INTERFACES_LIST \
BUS_GENERIC_INTERFACES_LIST \
"org.freedesktop.systemd1.Manager\0"
const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs);
@ -219,17 +224,18 @@ static int bus_manager_append_tainted(Manager *m, DBusMessageIter *i, const char
assert(i);
assert(property);
if (path_is_mount_point("/usr") > 0 || dir_is_empty("/usr") > 0)
e = stpcpy(e, "usr-separate-fs");
if (m->taint_usr)
e = stpcpy(e, "usr-separate-fs ");
if (readlink_malloc("/etc/mtab", &p) < 0) {
if (e != buf)
e = stpcpy(e, " ");
e = stpcpy(e, "etc-mtab-not-symlink");
} else
if (readlink_malloc("/etc/mtab", &p) < 0)
e = stpcpy(e, "etc-mtab-not-symlink ");
else
free(p);
t = buf;
if (access("/proc/cgroups", F_OK) < 0)
e = stpcpy(e, "cgroups-missing ");
t = strstrip(buf);
if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
return -ENOMEM;
@ -1014,14 +1020,16 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (!e)
goto oom;
if (!(reply = dbus_message_new_method_return(message)))
if (!(reply = dbus_message_new_method_return(message))) {
strv_free(e);
goto oom;
}
strv_free(m->environment);
m->environment = e;
} else
return bus_default_message_handler(m, connection, message, NULL, properties);
return bus_default_message_handler(m, connection, message, NULL, INTERFACES_LIST, properties);
if (job_type != _JOB_TYPE_INVALID) {
const char *name, *smode, *old_name = NULL;
@ -1102,8 +1110,6 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
goto oom;
}
free(path);
if (reply) {
if (!dbus_connection_send(connection, reply, NULL))
goto oom;
@ -1111,6 +1117,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
dbus_message_unref(reply);
}
free(path);
return DBUS_HANDLER_RESULT_HANDLED;
oom:

View File

@ -50,6 +50,10 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Mount\0"
const char bus_mount_interface[] _introspect_("Mount") = BUS_MOUNT_INTERFACE;
const char bus_mount_invalidating_properties[] =
@ -59,8 +63,7 @@ const char bus_mount_invalidating_properties[] =
"ExecMount\0"
"ExecUnmount\0"
"ExecRemount\0"
"ControlPID\0"
"\0";
"ControlPID\0";
static int bus_mount_append_what(Manager *n, DBusMessageIter *i, const char *property, void *data) {
Mount *m = data;
@ -151,5 +154,5 @@ DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMess
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -41,6 +41,10 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Path\0"
const char bus_path_interface[] _introspect_("Path") = BUS_PATH_INTERFACE;
static int bus_path_append_paths(Manager *m, DBusMessageIter *i, const char *property, void *data) {
@ -94,5 +98,5 @@ DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessa
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -26,34 +26,14 @@
#include "dbus-service.h"
#ifdef HAVE_SYSV_COMPAT
#define BUS_SERVICE_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Service\">\n" \
" <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Restart\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"PIDFile\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"NotifyAccess\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"RestartUSec\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \
BUS_EXEC_COMMAND_INTERFACE("ExecStart") \
BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \
BUS_EXEC_COMMAND_INTERFACE("ExecReload") \
BUS_EXEC_COMMAND_INTERFACE("ExecStop") \
BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \
BUS_EXEC_CONTEXT_INTERFACE \
" <property name=\"PermissionsStartOnly\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RootDirectoryStartOnly\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RemainAfterExit\" type=\"b\" access=\"read\"/>\n" \
BUS_EXEC_STATUS_INTERFACE("ExecMain") \
" <property name=\"MainPID\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
#define BUS_SERVICE_SYSV_INTERFACE_FRAGMENT \
" <property name=\"SysVStartPriority\" type=\"i\" access=\"read\"/>\n" \
" <property name=\"SysVRunLevels\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"SysVPath\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"BusName\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"StatusText\" type=\"s\" access=\"read\"/>\n" \
" </interface>\n"
" <property name=\"SysVPath\" type=\"s\" access=\"read\"/>\n"
#else
#define BUS_SERVICE_SYSV_INTERFACE_FRAGMENT ""
#endif
#define BUS_SERVICE_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Service\">\n" \
" <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
@ -77,8 +57,10 @@
" <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"BusName\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"StatusText\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"FsckPassNo\" type=\"i\" access=\"read\"/>\n" \
" <property name=\"Sockets\" type=\"as\" access=\"read\"/>\n" \
BUS_SERVICE_SYSV_INTERFACE_FRAGMENT \
" </interface>\n"
#endif
#define INTROSPECTION \
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
@ -90,6 +72,10 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Service\0"
const char bus_service_interface[] _introspect_("Service") = BUS_SERVICE_INTERFACE;
const char bus_service_invalidating_properties[] =
@ -102,8 +88,7 @@ const char bus_service_invalidating_properties[] =
"ExecMain\0"
"MainPID\0"
"ControlPID\0"
"StatusText\0"
"\0";
"StatusText\0";
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_type, service_type, ServiceType);
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_restart, service_restart, ServiceRestart);
@ -132,18 +117,17 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio
BUS_EXEC_STATUS_PROPERTIES("org.freedesktop.systemd1.Service", u->service.main_exec_status, "ExecMain"),
{ "org.freedesktop.systemd1.Service", "MainPID", bus_property_append_pid, "u", &u->service.main_pid },
{ "org.freedesktop.systemd1.Service", "ControlPID", bus_property_append_pid, "u", &u->service.control_pid },
#ifdef HAVE_SYSV_COMPAT
{ "org.freedesktop.systemd1.Service", "SysVPath", bus_property_append_string, "s", u->service.sysv_path },
#endif
{ "org.freedesktop.systemd1.Service", "BusName", bus_property_append_string, "s", u->service.bus_name },
{ "org.freedesktop.systemd1.Service", "StatusText", bus_property_append_string, "s", u->service.status_text },
{ "org.freedesktop.systemd1.Service", "Sockets", bus_unit_append_dependencies, "as", u->service.configured_sockets },
#ifdef HAVE_SYSV_COMPAT
{ "org.freedesktop.systemd1.Service", "SysVRunLevels", bus_property_append_string, "s", u->service.sysv_runlevels },
{ "org.freedesktop.systemd1.Service", "SysVStartPriority", bus_property_append_int, "i", &u->service.sysv_start_priority },
{ "org.freedesktop.systemd1.Service", "SysVPath", bus_property_append_string, "s", u->service.sysv_path },
#endif
{ "org.freedesktop.systemd1.Service", "FsckPassNo", bus_property_append_int, "i", &u->service.fsck_passno },
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, connection, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, connection, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -38,6 +38,10 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Snapshot\0"
const char bus_snapshot_interface[] _introspect_("Snapshot") = BUS_SNAPSHOT_INTERFACE;
DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
@ -60,7 +64,7 @@ DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusM
goto oom;
} else
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
if (reply) {
if (!dbus_connection_send(c, reply, NULL))

View File

@ -64,6 +64,10 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Socket\0"
const char bus_socket_interface[] _introspect_("Socket") = BUS_SOCKET_INTERFACE;
const char bus_socket_invalidating_properties[] =
@ -73,12 +77,12 @@ const char bus_socket_invalidating_properties[] =
"ExecStopPost\0"
"ControlPID\0"
"NAccepted\0"
"NConnections\0"
"\0";
"NConnections\0";
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
const BusProperty properties[] = {
BUS_UNIT_PROPERTIES,
{ "org.freedesktop.systemd1.Socket", "BindIPv6Only", bus_socket_append_bind_ipv6_only, "s", &u->socket.bind_ipv6_only },
@ -109,5 +113,5 @@ DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMes
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -47,6 +47,10 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Swap\0"
const char bus_swap_interface[] _introspect_("Swap") = BUS_SWAP_INTERFACE;
const char bus_swap_invalidating_properties[] =
@ -54,8 +58,7 @@ const char bus_swap_invalidating_properties[] =
"Priority\0"
"ExecActivate\0"
"ExecDeactivate\0"
"ControlPID\0"
"\0";
"ControlPID\0";
static int bus_swap_append_priority(Manager *m, DBusMessageIter *i, const char *property, void *data) {
Swap *s = data;
@ -93,5 +96,5 @@ DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessa
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -38,6 +38,10 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Target\0"
const char bus_target_interface[] _introspect_("Target") = BUS_TARGET_INTERFACE;
DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
@ -46,5 +50,5 @@ DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMes
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -42,12 +42,15 @@
BUS_INTROSPECTABLE_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Timer\0"
const char bus_timer_interface[] _introspect_("Timer") = BUS_TIMER_INTERFACE;
const char bus_timer_invalidating_properties[] =
"Timers\0"
"NextElapseUSec\0"
"\0";
"NextElapseUSec\0";
static int bus_timer_append_timers(Manager *m, DBusMessageIter *i, const char *property, void *data) {
Timer *p = data;
@ -119,5 +122,5 @@ DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMess
{ NULL, NULL, NULL, NULL, NULL }
};
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, properties);
return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
}

View File

@ -37,8 +37,7 @@ const char bus_unit_interface[] _introspect_("Unit") = BUS_UNIT_INTERFACE;
"ActiveExitTimestamp\0" \
"InactiveEnterTimestamp\0" \
"Job\0" \
"NeedDaemonReload\0" \
"\0"
"NeedDaemonReload\0"
int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, void *data) {
char *t;
@ -456,8 +455,6 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
goto oom;
}
free(path);
if (reply) {
if (!dbus_connection_send(connection, reply, NULL))
goto oom;
@ -465,6 +462,8 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
dbus_message_unref(reply);
}
free(path);
return DBUS_HANDLER_RESULT_HANDLED;
oom:
@ -569,6 +568,8 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
if (r == -ENOENT) {
DBusError e;
dbus_error_init(&e);
dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown unit");
return bus_send_error_reply(m, connection, message, &e, r);
}

View File

@ -102,8 +102,14 @@
" <property name=\"ControlGroup\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"NeedDaemonReload\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"JobTimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ConditionResult\" type=\"b\" access=\"read\"/>\n" \
" </interface>\n"
#define BUS_UNIT_INTERFACES_LIST \
BUS_GENERIC_INTERFACES_LIST \
"org.freedesktop.systemd1.Unit\0"
#define BUS_UNIT_PROPERTIES \
{ "org.freedesktop.systemd1.Unit", "Id", bus_property_append_string, "s", u->meta.id }, \
{ "org.freedesktop.systemd1.Unit", "Names", bus_unit_append_names, "as", u }, \
@ -128,10 +134,10 @@
{ "org.freedesktop.systemd1.Unit", "ActiveState", bus_unit_append_active_state, "s", u }, \
{ "org.freedesktop.systemd1.Unit", "SubState", bus_unit_append_sub_state, "s", u }, \
{ "org.freedesktop.systemd1.Unit", "FragmentPath", bus_property_append_string, "s", u->meta.fragment_path }, \
{ "org.freedesktop.systemd1.Unit", "InactiveExitTimestamp",bus_property_append_uint64, "t", &u->meta.inactive_exit_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_uint64, "t", &u->meta.active_enter_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp", bus_property_append_uint64, "t", &u->meta.active_exit_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "InactiveEnterTimestamp",bus_property_append_uint64, "t", &u->meta.inactive_enter_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "InactiveExitTimestamp",bus_property_append_usec, "t", &u->meta.inactive_exit_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_usec, "t", &u->meta.active_enter_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp", bus_property_append_usec, "t", &u->meta.active_exit_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "InactiveEnterTimestamp",bus_property_append_usec, "t", &u->meta.inactive_enter_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "CanStart", bus_unit_append_can_start, "b", u }, \
{ "org.freedesktop.systemd1.Unit", "CanStop", bus_unit_append_can_stop, "b", u }, \
{ "org.freedesktop.systemd1.Unit", "CanReload", bus_unit_append_can_reload, "b", u }, \
@ -145,7 +151,9 @@
{ "org.freedesktop.systemd1.Unit", "DefaultControlGroup", bus_unit_append_default_cgroup, "s", u }, \
{ "org.freedesktop.systemd1.Unit", "ControlGroup", bus_unit_append_cgroups, "as", u }, \
{ "org.freedesktop.systemd1.Unit", "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", u }, \
{ "org.freedesktop.systemd1.Unit", "JobTimeoutUSec", bus_property_append_usec, "t", &u->meta.job_timeout }
{ "org.freedesktop.systemd1.Unit", "JobTimeoutUSec", bus_property_append_usec, "t", &u->meta.job_timeout }, \
{ "org.freedesktop.systemd1.Unit", "ConditionTimestamp", bus_property_append_usec, "t", &u->meta.condition_timestamp.realtime }, \
{ "org.freedesktop.systemd1.Unit", "ConditionResult", bus_property_append_bool, "b", &u->meta.condition_result }
int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_unit_append_following(Manager *m, DBusMessageIter *i, const char *property, void *data);

View File

@ -176,8 +176,8 @@ static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
}
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
free(w);
close_nointr_nofail(w->fd);
free(w);
return FALSE;
}
@ -236,7 +236,7 @@ static int bus_timeout_arm(Manager *m, Watch *w) {
if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
its.it_interval = its.it_interval;
its.it_interval = its.it_value;
}
if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
@ -269,7 +269,7 @@ static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
if (!(w = new0(Watch, 1)))
return FALSE;
if (!(w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
goto fail;
w->type = WATCH_DBUS_TIMEOUT;
@ -955,7 +955,8 @@ static int bus_init_private(Manager *m) {
if (getpid() != 1)
return 0;
if (!(m->private_bus = dbus_server_listen("unix:abstract=/org/freedesktop/systemd1/private", &error))) {
unlink("/run/systemd/private");
if (!(m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error))) {
log_error("Failed to create private D-Bus server: %s", error.message);
r = -EIO;
goto fail;
@ -1213,12 +1214,20 @@ oom:
return -ENOMEM;
}
DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBusMessage *message, const char*introspection, const BusProperty *properties) {
DBusHandlerResult bus_default_message_handler(
Manager *m,
DBusConnection *c,
DBusMessage *message,
const char *introspection,
const char *interfaces,
const BusProperty *properties) {
DBusError error;
DBusMessage *reply = NULL;
int r;
assert(m);
assert(c);
assert(message);
dbus_error_init(&error);
@ -1269,6 +1278,13 @@ DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBu
if (!dbus_message_iter_close_container(&iter, &sub))
goto oom;
} else {
if (!nulstr_contains(interfaces, interface))
dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
else
dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
return bus_send_error_reply(m, c, message, &error, -EINVAL);
}
} else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && properties) {
@ -1283,6 +1299,11 @@ DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBu
DBUS_TYPE_INVALID))
return bus_send_error_reply(m, c, message, &error, -EINVAL);
if (interface[0] && !nulstr_contains(interfaces, interface)) {
dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
return bus_send_error_reply(m, c, message, &error, -EINVAL);
}
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
@ -1316,6 +1337,7 @@ DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBu
if (!dbus_message_iter_close_container(&iter, &sub))
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && properties) {
const char *interface, *property;
DBusMessageIter iter;
@ -1366,8 +1388,20 @@ DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBu
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
} else
return bus_send_error_reply(m, c, message, NULL, -EINVAL);
} else {
if (p->property)
dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
else if (!nulstr_contains(interfaces, interface))
dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
else
dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
return bus_send_error_reply(m, c, message, &error, -EINVAL);
}
} else if (!nulstr_contains(interfaces, dbus_message_get_interface(message))) {
dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
return bus_send_error_reply(m, c, message, &error, -EINVAL);
}
if (reply) {

View File

@ -32,6 +32,14 @@
#define DBUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface"
#endif
#ifndef DBUS_ERROR_UNKNOWN_PROPERTY
#define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
#endif
#ifndef DBUS_ERROR_PROPERTY_READ_ONLY
#define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
#endif
#include "manager.h"
typedef int (*BusPropertyCallback)(Manager *m, DBusMessageIter *iter, const char *property, void *data);
@ -84,6 +92,11 @@ typedef struct BusProperty {
" </method>\n" \
"</interface>\n"
#define BUS_GENERIC_INTERFACES_LIST \
"org.freedesktop.DBus.Properties\0" \
"org.freedesktop.DBus.Introspectable\0" \
"org.freedesktop.DBus.Peer\0"
int bus_init(Manager *m, bool try_bus_connect);
void bus_done(Manager *m);
@ -94,7 +107,7 @@ void bus_timeout_event(Manager *m, Watch *w, int events);
int bus_query_pid(Manager *m, const char *name);
DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBusMessage *message, const char* introspection, const BusProperty *properties);
DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBusMessage *message, const char* introspection, const char *interfaces, const BusProperty *properties);
DBusHandlerResult bus_send_error_reply(Manager *m, DBusConnection *c, DBusMessage *message, DBusError *bus_error, int error);
int bus_broadcast(Manager *m, DBusMessage *message);

35
src/def.h Normal file
View File

@ -0,0 +1,35 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#ifndef foodefhfoo
#define foodefhfoo
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "util.h"
#define DEFAULT_TIMEOUT_USEC (3*USEC_PER_MINUTE)
#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC)
#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
#define SIGNALS_IGNORE SIGKILL,SIGPIPE
#endif

View File

@ -29,6 +29,7 @@
#include "log.h"
#include "unit-name.h"
#include "dbus-device.h"
#include "def.h"
static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
[DEVICE_DEAD] = UNIT_INACTIVE,

View File

@ -55,6 +55,7 @@
#include "exit-status.h"
#include "missing.h"
#include "utmp-wtmp.h"
#include "def.h"
/* This assumes there is a 'tty' group */
#define TTY_MODE 0620
@ -173,9 +174,9 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons
zero(sa);
sa.sa.sa_family = AF_UNIX;
strncpy(sa.un.sun_path+1, LOGGER_SOCKET, sizeof(sa.un.sun_path)-1);
strncpy(sa.un.sun_path, LOGGER_SOCKET, sizeof(sa.un.sun_path));
if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + sizeof(LOGGER_SOCKET) - 1) < 0) {
if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + sizeof(LOGGER_SOCKET) - 1) < 0) {
close_nointr_nofail(fd);
return -errno;
}
@ -645,7 +646,7 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_
char **i;
/* Final step, initialize any manually set supplementary groups */
ngroups_max = (int) sysconf(_SC_NGROUPS_MAX);
assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
if (!(gids = new(gid_t, ngroups_max)))
return -ENOMEM;
@ -980,7 +981,7 @@ int exec_spawn(ExecCommand *command,
/* This string must fit in 10 chars (i.e. the length
* of "/sbin/init") */
rename_process("sd:exec");
rename_process("sd.exec");
/* We reset exactly these signals, since they are the
* only ones we set to SIG_IGN in the main daemon. All
@ -1248,6 +1249,15 @@ int exec_spawn(ExecCommand *command,
}
}
if (context->capability_bounding_set_drop)
for (i = 0; i <= CAP_LAST_CAP; i++)
if (context->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i)) {
if (prctl(PR_CAPBSET_DROP, i) < 0) {
r = EXIT_CAPABILITIES;
goto fail_child;
}
}
if (context->user)
if (enforce_user(context, uid) < 0) {
r = EXIT_USER;
@ -1640,7 +1650,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
fprintf(f,
"%sSyslogFacility: %s\n"
"%sSyslogLevel: %s\n",
prefix, log_facility_to_string(LOG_FAC(c->syslog_priority)),
prefix, log_facility_unshifted_to_string(c->syslog_priority >> 3),
prefix, log_level_to_string(LOG_PRI(c->syslog_priority)));
if (c->capabilities) {
@ -1663,15 +1673,15 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
(c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
if (c->capability_bounding_set_drop) {
fprintf(f, "%sCapabilityBoundingSetDrop:", prefix);
fprintf(f, "%sCapabilityBoundingSet:", prefix);
for (i = 0; i <= CAP_LAST_CAP; i++)
if (c->capability_bounding_set_drop & (1 << i)) {
if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i))) {
char *t;
if ((t = cap_to_name(i))) {
fprintf(f, " %s", t);
free(t);
cap_free(t);
}
}
@ -1923,7 +1933,6 @@ DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
static const char* const kill_mode_table[_KILL_MODE_MAX] = {
[KILL_CONTROL_GROUP] = "control-group",
[KILL_PROCESS_GROUP] = "process-group",
[KILL_PROCESS] = "process",
[KILL_NONE] = "none"
};

View File

@ -39,16 +39,10 @@ struct CGroupBonding;
#include "list.h"
#include "util.h"
/* Abstract namespace! */
#define LOGGER_SOCKET "/org/freedesktop/systemd1/logger"
/* This doesn't really belong here, but I couldn't find a better place to put this. */
#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
#define SIGNALS_IGNORE SIGKILL,SIGPIPE
#define LOGGER_SOCKET "/run/systemd/logger"
typedef enum KillMode {
KILL_CONTROL_GROUP = 0,
KILL_PROCESS_GROUP,
KILL_PROCESS,
KILL_NONE,
_KILL_MODE_MAX,

View File

@ -106,6 +106,9 @@ static int parse_proc_cmdline(void) {
int r;
size_t l;
if (detect_container(NULL) > 0)
return 0;
if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
return 0;
@ -262,7 +265,7 @@ int main(int argc, char *argv[]) {
r = EXIT_SUCCESS;
if (status.si_code == CLD_EXITED && (status.si_status & 1))
touch("/dev/.systemd/quotacheck");
touch("/run/systemd/quotacheck");
finish:
if (udev_device)

127
src/getty-generator.c Normal file
View File

@ -0,0 +1,127 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "log.h"
#include "util.h"
#include "unit-name.h"
const char *arg_dest = "/tmp";
static int add_symlink(const char *fservice, const char *tservice) {
char *from = NULL, *to = NULL;
int r;
asprintf(&from, SYSTEM_DATA_UNIT_PATH "/%s", fservice);
asprintf(&to, "%s/getty.target.wants/%s", arg_dest, tservice);
if (!from || !to) {
log_error("Out of memory");
r = -ENOMEM;
goto finish;
}
mkdir_parents(to, 0755);
if ((r = symlink(from, to)) < 0) {
log_error("Failed to create symlink from %s to %s: %m", from, to);
r = -errno;
}
finish:
free(from);
free(to);
return r;
}
int main(int argc, char *argv[]) {
int r = EXIT_SUCCESS;
char *active;
if (argc > 2) {
log_error("This program takes one or no arguments.");
return EXIT_FAILURE;
}
if (argc > 1)
arg_dest = argv[1];
log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
log_parse_environment();
log_open();
if (detect_container(NULL) > 0) {
log_debug("Automatic adding console shell.");
if (add_symlink("console-shell.service", "console-shell.service") < 0)
r = EXIT_FAILURE;
/* Don't add any further magic if we are in a container */
goto finish;
}
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
const char *tty;
truncate_nl(active);
if ((tty = strrchr(active, ' ')))
tty ++;
else
tty = active;
/* Automatically add in a serial getty on the kernel
* console */
if (!tty_is_vc(tty)) {
char *n;
/* We assume that gettys on virtual terminals are
* started via manual configuration and do this magic
* only for non-VC terminals. */
log_debug("Automatically adding serial getty for /dev/%s.", tty);
if (!(n = unit_name_replace_instance("serial-getty@.service", tty)) ||
add_symlink("serial-getty@.service", n) < 0)
r = EXIT_FAILURE;
free(n);
}
free(active);
}
/* Automatically add in a serial getty on the first
* virtualizer console */
if (access("/sys/class/tty/hvc0", F_OK) == 0) {
log_debug("Automatic adding serial getty for hvc0.");
if (add_symlink("serial-getty@.service", "serial-getty@hvc0.service") < 0)
r = EXIT_FAILURE;
}
finish:
return r;
}

View File

@ -89,9 +89,9 @@ public class MyStatusIcon : StatusIcon {
public MyStatusIcon() throws GLib.Error {
GLib.Object(icon_name : "dialog-password");
set_title("System Password");
set_title("System Password Request");
directory = File.new_for_path("/dev/.systemd/ask-password/");
directory = File.new_for_path("/run/systemd/ask-password/");
file_monitor = directory.monitor_directory(0);
file_monitor.changed.connect(file_monitor_changed);
@ -145,7 +145,6 @@ public class MyStatusIcon : StatusIcon {
if (current == null)
set_visible(false);
}
bool load_password() throws GLib.Error {
@ -179,6 +178,7 @@ public class MyStatusIcon : StatusIcon {
} catch (GLib.Error e) {
message = "Please Enter System Password!";
}
set_tooltip_text(message);
try {
@ -239,8 +239,7 @@ public class MyStatusIcon : StatusIcon {
null);
OutputStream stream = new UnixOutputStream(to_process, true);
#if LIBNOTIFY07
#if VALA_0_12
stream.write(password.data, null);
#else
stream.write(password, password.length, null);

View File

@ -174,16 +174,36 @@ int hostname_setup(void) {
else
log_warning("Failed to read configured hostname: %s", strerror(-r));
hn = "localhost";
hn = NULL;
} else
hn = b;
if (!hn) {
/* Don't override the hostname if it is unset and not
* explicitly configured */
char *old_hostname = NULL;
if ((old_hostname = gethostname_malloc())) {
bool already_set;
already_set = old_hostname[0] != 0;
free(old_hostname);
if (already_set)
goto finish;
}
hn = "localhost";
}
if (sethostname(hn, strlen(hn)) < 0) {
log_warning("Failed to set hostname to <%s>: %m", hn);
r = -errno;
} else
log_info("Set hostname to <%s>.", hn);
finish:
free(b);
return r;

View File

@ -313,7 +313,7 @@ bool job_is_runnable(Job *j) {
* type. */
/* First check if there is an override */
if (j->ignore_deps)
if (j->ignore_order)
return true;
if (j->type == JOB_START ||
@ -694,7 +694,8 @@ static const char* const job_mode_table[_JOB_MODE_MAX] = {
[JOB_FAIL] = "fail",
[JOB_REPLACE] = "replace",
[JOB_ISOLATE] = "isolate",
[JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies"
[JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
[JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
};
DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);

View File

@ -64,10 +64,11 @@ enum JobState {
};
enum JobMode {
JOB_FAIL,
JOB_REPLACE,
JOB_ISOLATE,
JOB_IGNORE_DEPENDENCIES,
JOB_FAIL, /* Fail if a conflicting job is already queued */
JOB_REPLACE, /* Replace an existing conflicting job */
JOB_ISOLATE, /* Start a unit, and stop all others */
JOB_IGNORE_DEPENDENCIES, /* Ignore both requirement and ordering dependencies */
JOB_IGNORE_REQUIREMENTS, /* Ignore requirement dependencies */
_JOB_MODE_MAX,
_JOB_MODE_INVALID = -1
};
@ -130,7 +131,7 @@ struct Job {
bool override:1;
bool in_dbus_queue:1;
bool sent_dbus_new_signal:1;
bool ignore_deps:1;
bool ignore_order:1;
};
Job* job_new(Manager *m, JobType type, Unit *unit);

View File

@ -154,50 +154,6 @@ fail:
return r;
}
static int read_priority(const char **buf) {
int priority;
size_t n;
const char *p;
int a, b, c;
assert(buf);
assert(*buf);
p = *buf;
n = strlen(p);
if (n < 3 || p[0] != '<')
goto fail;
if (p[2] == '>') {
a = b = 0;
c = undecchar(p[1]);
p += 3;
} else if (n >= 4 && p[3] == '>') {
a = 0;
b = undecchar(p[1]);
c = undecchar(p[2]);
p += 4;
} else if (n >= 5 && p[4] == '>') {
a = undecchar(p[1]);
b = undecchar(p[2]);
c = undecchar(p[3]);
p += 5;
} else
goto fail;
if (a < 0 || b < 0 || c < 0)
goto fail;
*buf = p;
priority = 100*a + 10*b + c;
return LOG_PRI(priority);
fail:
return LOG_INFO;
}
static void skip_date(const char **buf) {
enum {
LETTER,
@ -334,17 +290,26 @@ static void skip_pid(const char **buf) {
static int write_message(Server *s, const char *buf, struct ucred *ucred) {
ssize_t k;
char priority[4], pid[16];
char priority[6], pid[16];
struct iovec iovec[5];
unsigned i = 0;
char *process = NULL;
int r = 0;
int prio = LOG_USER | LOG_INFO;
assert(s);
assert(buf);
parse_syslog_priority((char**) &buf, &prio);
if (*buf == 0)
return 0;
if ((prio & LOG_FACMASK) == 0)
prio = LOG_USER | LOG_PRI(prio);
/* First, set priority field */
snprintf(priority, sizeof(priority), "<%i>", read_priority(&buf));
snprintf(priority, sizeof(priority), "<%i>", prio);
char_array_0(priority);
IOVEC_SET_STRING(iovec[i++], priority);
@ -354,7 +319,9 @@ static int write_message(Server *s, const char *buf, struct ucred *ucred) {
/* Then, add process if set */
if (read_process(&buf, &iovec[i]) > 0)
i++;
else if (ucred && get_process_name(ucred->pid, &process) >= 0)
else if (ucred &&
ucred->pid > 0 &&
get_process_name(ucred->pid, &process) >= 0)
IOVEC_SET_STRING(iovec[i++], process);
/* Skip the stored PID if we have a better one */

View File

@ -30,6 +30,8 @@
#include <sys/mount.h>
#include <linux/fs.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "unit.h"
#include "strv.h"
@ -48,6 +50,7 @@ static int config_parse_warn_compat(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -62,6 +65,7 @@ static int config_parse_deps(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -108,6 +112,7 @@ static int config_parse_names(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -154,6 +159,7 @@ static int config_parse_string_printf(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -187,6 +193,7 @@ static int config_parse_listen(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -249,6 +256,7 @@ static int config_parse_socket_bind(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -283,6 +291,7 @@ static int config_parse_nice(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -316,6 +325,7 @@ static int config_parse_oom_score_adjust(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -349,6 +359,7 @@ static int config_parse_mode(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -383,6 +394,7 @@ static int config_parse_exec(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -500,6 +512,7 @@ static int config_parse_usec(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -527,6 +540,7 @@ static int config_parse_bindtodevice(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -559,6 +573,7 @@ static int config_parse_facility(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -571,12 +586,12 @@ static int config_parse_facility(
assert(rvalue);
assert(data);
if ((x = log_facility_from_string(rvalue)) < 0) {
if ((x = log_facility_unshifted_from_string(rvalue)) < 0) {
log_error("[%s:%u] Failed to parse log facility, ignoring: %s", filename, line, rvalue);
return 0;
}
*o = LOG_MAKEPRI(x, LOG_PRI(*o));
*o = (x << 3) | LOG_PRI(*o);
return 0;
}
@ -586,6 +601,7 @@ static int config_parse_level(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -603,7 +619,7 @@ static int config_parse_level(
return 0;
}
*o = LOG_MAKEPRI(LOG_FAC(*o), x);
*o = (*o & LOG_FACMASK) | x;
return 0;
}
@ -612,6 +628,7 @@ static int config_parse_io_class(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -640,6 +657,7 @@ static int config_parse_io_priority(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -668,6 +686,7 @@ static int config_parse_cpu_sched_policy(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -697,6 +716,7 @@ static int config_parse_cpu_sched_prio(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -726,6 +746,7 @@ static int config_parse_cpu_affinity(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -771,6 +792,7 @@ static int config_parse_capabilities(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -803,6 +825,7 @@ static int config_parse_secure_bits(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -844,6 +867,7 @@ static int config_parse_bounding_set(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -852,12 +876,24 @@ static int config_parse_bounding_set(
char *w;
size_t l;
char *state;
bool invert = false;
uint64_t sum = 0;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (rvalue[0] == '~') {
invert = true;
rvalue++;
}
/* Note that we store this inverted internally, since the
* kernel wants it like this. But we actually expose it
* non-inverted everywhere to have a fully normalized
* interface. */
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
@ -874,9 +910,14 @@ static int config_parse_bounding_set(
return 0;
}
c->capability_bounding_set_drop |= 1 << cap;
sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
}
if (invert)
c->capability_bounding_set_drop |= sum;
else
c->capability_bounding_set_drop |= ~sum;
return 0;
}
@ -885,6 +926,7 @@ static int config_parse_timer_slack_nsec(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -912,6 +954,7 @@ static int config_parse_limit(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -924,7 +967,9 @@ static int config_parse_limit(
assert(rvalue);
assert(data);
if (safe_atollu(rvalue, &u) < 0) {
if (streq(rvalue, "infinity"))
u = (unsigned long long) RLIM_INFINITY;
else if (safe_atollu(rvalue, &u) < 0) {
log_error("[%s:%u] Failed to parse resource value, ignoring: %s", filename, line, rvalue);
return 0;
}
@ -942,6 +987,7 @@ static int config_parse_cgroup(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -976,6 +1022,7 @@ static int config_parse_sysv_priority(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1003,6 +1050,7 @@ static int config_parse_fsck_passno(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1031,6 +1079,7 @@ static int config_parse_kill_signal(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1057,6 +1106,7 @@ static int config_parse_mount_flags(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1094,6 +1144,7 @@ static int config_parse_timer(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1134,6 +1185,7 @@ static int config_parse_timer_unit(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1168,6 +1220,7 @@ static int config_parse_path_spec(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1214,6 +1267,7 @@ static int config_parse_path_unit(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1248,6 +1302,7 @@ static int config_parse_socket_service(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1282,6 +1337,7 @@ static int config_parse_service_sockets(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1336,6 +1392,7 @@ static int config_parse_env_file(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1366,6 +1423,7 @@ static int config_parse_ip_tos(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1392,10 +1450,12 @@ static int config_parse_condition_path(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ConditionType cond = ltype;
Unit *u = data;
bool trigger, negate;
Condition *c;
@ -1416,23 +1476,24 @@ static int config_parse_condition_path(
return 0;
}
if (!(c = condition_new(streq(lvalue, "ConditionPathExists") ? CONDITION_PATH_EXISTS : CONDITION_DIRECTORY_NOT_EMPTY,
rvalue, trigger, negate)))
if (!(c = condition_new(cond, rvalue, trigger, negate)))
return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
return 0;
}
static int config_parse_condition_kernel(
static int config_parse_condition_string(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ConditionType cond = ltype;
Unit *u = data;
bool trigger, negate;
Condition *c;
@ -1448,38 +1509,7 @@ static int config_parse_condition_kernel(
if ((negate = rvalue[0] == '!'))
rvalue++;
if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, trigger, negate)))
return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
return 0;
}
static int config_parse_condition_virt(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
const char *rvalue,
void *data,
void *userdata) {
Unit *u = data;
bool trigger, negate;
Condition *c;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!'))
rvalue++;
if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, trigger, negate)))
if (!(c = condition_new(cond, rvalue, trigger, negate)))
return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@ -1491,6 +1521,7 @@ static int config_parse_condition_null(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -1698,9 +1729,8 @@ static void dump_items(FILE *f, const ConfigItem *items) {
{ config_parse_notify_access, "ACCESS" },
{ config_parse_ip_tos, "TOS" },
{ config_parse_condition_path, "CONDITION" },
{ config_parse_condition_kernel, "CONDITION" },
{ config_parse_condition_string, "CONDITION" },
{ config_parse_condition_null, "CONDITION" },
{ config_parse_condition_virt, "CONDITION" },
};
assert(f);
@ -1746,178 +1776,180 @@ static int load_from_path(Unit *u, const char *path) {
};
#define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \
{ "WorkingDirectory", config_parse_path, &(context).working_directory, section }, \
{ "RootDirectory", config_parse_path, &(context).root_directory, section }, \
{ "User", config_parse_string_printf, &(context).user, section }, \
{ "Group", config_parse_string_printf, &(context).group, section }, \
{ "SupplementaryGroups", config_parse_strv, &(context).supplementary_groups, section }, \
{ "Nice", config_parse_nice, &(context), section }, \
{ "OOMScoreAdjust", config_parse_oom_score_adjust,&(context), section }, \
{ "IOSchedulingClass", config_parse_io_class, &(context), section }, \
{ "IOSchedulingPriority", config_parse_io_priority, &(context), section }, \
{ "CPUSchedulingPolicy", config_parse_cpu_sched_policy,&(context), section }, \
{ "CPUSchedulingPriority", config_parse_cpu_sched_prio, &(context), section }, \
{ "CPUSchedulingResetOnFork", config_parse_bool, &(context).cpu_sched_reset_on_fork, section }, \
{ "CPUAffinity", config_parse_cpu_affinity, &(context), section }, \
{ "UMask", config_parse_mode, &(context).umask, section }, \
{ "Environment", config_parse_strv, &(context).environment, section }, \
{ "EnvironmentFile", config_parse_env_file, &(context).environment_files, section }, \
{ "StandardInput", config_parse_input, &(context).std_input, section }, \
{ "StandardOutput", config_parse_output, &(context).std_output, section }, \
{ "StandardError", config_parse_output, &(context).std_error, section }, \
{ "TTYPath", config_parse_path, &(context).tty_path, section }, \
{ "SyslogIdentifier", config_parse_string_printf, &(context).syslog_identifier, section }, \
{ "SyslogFacility", config_parse_facility, &(context).syslog_priority, section }, \
{ "SyslogLevel", config_parse_level, &(context).syslog_priority, section }, \
{ "SyslogLevelPrefix", config_parse_bool, &(context).syslog_level_prefix, section }, \
{ "Capabilities", config_parse_capabilities, &(context), section }, \
{ "SecureBits", config_parse_secure_bits, &(context), section }, \
{ "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context), section }, \
{ "TimerSlackNSec", config_parse_timer_slack_nsec,&(context), section }, \
{ "LimitCPU", config_parse_limit, &(context).rlimit[RLIMIT_CPU], section }, \
{ "LimitFSIZE", config_parse_limit, &(context).rlimit[RLIMIT_FSIZE], section }, \
{ "LimitDATA", config_parse_limit, &(context).rlimit[RLIMIT_DATA], section }, \
{ "LimitSTACK", config_parse_limit, &(context).rlimit[RLIMIT_STACK], section }, \
{ "LimitCORE", config_parse_limit, &(context).rlimit[RLIMIT_CORE], section }, \
{ "LimitRSS", config_parse_limit, &(context).rlimit[RLIMIT_RSS], section }, \
{ "LimitNOFILE", config_parse_limit, &(context).rlimit[RLIMIT_NOFILE], section }, \
{ "LimitAS", config_parse_limit, &(context).rlimit[RLIMIT_AS], section }, \
{ "LimitNPROC", config_parse_limit, &(context).rlimit[RLIMIT_NPROC], section }, \
{ "LimitMEMLOCK", config_parse_limit, &(context).rlimit[RLIMIT_MEMLOCK], section }, \
{ "LimitLOCKS", config_parse_limit, &(context).rlimit[RLIMIT_LOCKS], section }, \
{ "LimitSIGPENDING", config_parse_limit, &(context).rlimit[RLIMIT_SIGPENDING], section }, \
{ "LimitMSGQUEUE", config_parse_limit, &(context).rlimit[RLIMIT_MSGQUEUE], section }, \
{ "LimitNICE", config_parse_limit, &(context).rlimit[RLIMIT_NICE], section }, \
{ "LimitRTPRIO", config_parse_limit, &(context).rlimit[RLIMIT_RTPRIO], section }, \
{ "LimitRTTIME", config_parse_limit, &(context).rlimit[RLIMIT_RTTIME], section }, \
{ "ControlGroup", config_parse_cgroup, u, section }, \
{ "ReadWriteDirectories", config_parse_path_strv, &(context).read_write_dirs, section }, \
{ "ReadOnlyDirectories", config_parse_path_strv, &(context).read_only_dirs, section }, \
{ "InaccessibleDirectories",config_parse_path_strv, &(context).inaccessible_dirs, section }, \
{ "PrivateTmp", config_parse_bool, &(context).private_tmp, section }, \
{ "MountFlags", config_parse_mount_flags, &(context), section }, \
{ "TCPWrapName", config_parse_string_printf, &(context).tcpwrap_name, section }, \
{ "PAMName", config_parse_string_printf, &(context).pam_name, section }, \
{ "KillMode", config_parse_kill_mode, &(context).kill_mode, section }, \
{ "KillSignal", config_parse_kill_signal, &(context).kill_signal, section }, \
{ "SendSIGKILL", config_parse_bool, &(context).send_sigkill, section }, \
{ "UtmpIdentifier", config_parse_string_printf, &(context).utmp_id, section }
{ "WorkingDirectory", config_parse_path, 0, &(context).working_directory, section }, \
{ "RootDirectory", config_parse_path, 0, &(context).root_directory, section }, \
{ "User", config_parse_string_printf, 0, &(context).user, section }, \
{ "Group", config_parse_string_printf, 0, &(context).group, section }, \
{ "SupplementaryGroups", config_parse_strv, 0, &(context).supplementary_groups, section }, \
{ "Nice", config_parse_nice, 0, &(context), section }, \
{ "OOMScoreAdjust", config_parse_oom_score_adjust,0, &(context), section }, \
{ "IOSchedulingClass", config_parse_io_class, 0, &(context), section }, \
{ "IOSchedulingPriority", config_parse_io_priority, 0, &(context), section }, \
{ "CPUSchedulingPolicy", config_parse_cpu_sched_policy,0, &(context), section }, \
{ "CPUSchedulingPriority", config_parse_cpu_sched_prio, 0, &(context), section }, \
{ "CPUSchedulingResetOnFork", config_parse_bool, 0, &(context).cpu_sched_reset_on_fork, section }, \
{ "CPUAffinity", config_parse_cpu_affinity, 0, &(context), section }, \
{ "UMask", config_parse_mode, 0, &(context).umask, section }, \
{ "Environment", config_parse_strv, 0, &(context).environment, section }, \
{ "EnvironmentFile", config_parse_env_file, 0, &(context).environment_files, section }, \
{ "StandardInput", config_parse_input, 0, &(context).std_input, section }, \
{ "StandardOutput", config_parse_output, 0, &(context).std_output, section }, \
{ "StandardError", config_parse_output, 0, &(context).std_error, section }, \
{ "TTYPath", config_parse_path, 0, &(context).tty_path, section }, \
{ "SyslogIdentifier", config_parse_string_printf, 0, &(context).syslog_identifier, section }, \
{ "SyslogFacility", config_parse_facility, 0, &(context).syslog_priority, section }, \
{ "SyslogLevel", config_parse_level, 0, &(context).syslog_priority, section }, \
{ "SyslogLevelPrefix", config_parse_bool, 0, &(context).syslog_level_prefix, section }, \
{ "Capabilities", config_parse_capabilities, 0, &(context), section }, \
{ "SecureBits", config_parse_secure_bits, 0, &(context), section }, \
{ "CapabilityBoundingSet", config_parse_bounding_set, 0, &(context), section }, \
{ "TimerSlackNSec", config_parse_timer_slack_nsec,0, &(context), section }, \
{ "LimitCPU", config_parse_limit, 0, &(context).rlimit[RLIMIT_CPU], section }, \
{ "LimitFSIZE", config_parse_limit, 0, &(context).rlimit[RLIMIT_FSIZE], section }, \
{ "LimitDATA", config_parse_limit, 0, &(context).rlimit[RLIMIT_DATA], section }, \
{ "LimitSTACK", config_parse_limit, 0, &(context).rlimit[RLIMIT_STACK], section }, \
{ "LimitCORE", config_parse_limit, 0, &(context).rlimit[RLIMIT_CORE], section }, \
{ "LimitRSS", config_parse_limit, 0, &(context).rlimit[RLIMIT_RSS], section }, \
{ "LimitNOFILE", config_parse_limit, 0, &(context).rlimit[RLIMIT_NOFILE], section }, \
{ "LimitAS", config_parse_limit, 0, &(context).rlimit[RLIMIT_AS], section }, \
{ "LimitNPROC", config_parse_limit, 0, &(context).rlimit[RLIMIT_NPROC], section }, \
{ "LimitMEMLOCK", config_parse_limit, 0, &(context).rlimit[RLIMIT_MEMLOCK], section }, \
{ "LimitLOCKS", config_parse_limit, 0, &(context).rlimit[RLIMIT_LOCKS], section }, \
{ "LimitSIGPENDING", config_parse_limit, 0, &(context).rlimit[RLIMIT_SIGPENDING], section }, \
{ "LimitMSGQUEUE", config_parse_limit, 0, &(context).rlimit[RLIMIT_MSGQUEUE], section }, \
{ "LimitNICE", config_parse_limit, 0, &(context).rlimit[RLIMIT_NICE], section }, \
{ "LimitRTPRIO", config_parse_limit, 0, &(context).rlimit[RLIMIT_RTPRIO], section }, \
{ "LimitRTTIME", config_parse_limit, 0, &(context).rlimit[RLIMIT_RTTIME], section }, \
{ "ControlGroup", config_parse_cgroup, 0, u, section }, \
{ "ReadWriteDirectories", config_parse_path_strv, 0, &(context).read_write_dirs, section }, \
{ "ReadOnlyDirectories", config_parse_path_strv, 0, &(context).read_only_dirs, section }, \
{ "InaccessibleDirectories",config_parse_path_strv, 0, &(context).inaccessible_dirs, section }, \
{ "PrivateTmp", config_parse_bool, 0, &(context).private_tmp, section }, \
{ "MountFlags", config_parse_mount_flags, 0, &(context), section }, \
{ "TCPWrapName", config_parse_string_printf, 0, &(context).tcpwrap_name, section }, \
{ "PAMName", config_parse_string_printf, 0, &(context).pam_name, section }, \
{ "KillMode", config_parse_kill_mode, 0, &(context).kill_mode, section }, \
{ "KillSignal", config_parse_kill_signal, 0, &(context).kill_signal, section }, \
{ "SendSIGKILL", config_parse_bool, 0, &(context).send_sigkill, section }, \
{ "UtmpIdentifier", config_parse_string_printf, 0, &(context).utmp_id, section }
const ConfigItem items[] = {
{ "Names", config_parse_names, u, "Unit" },
{ "Description", config_parse_string_printf, &u->meta.description, "Unit" },
{ "Requires", config_parse_deps, UINT_TO_PTR(UNIT_REQUIRES), "Unit" },
{ "RequiresOverridable", config_parse_deps, UINT_TO_PTR(UNIT_REQUIRES_OVERRIDABLE), "Unit" },
{ "Requisite", config_parse_deps, UINT_TO_PTR(UNIT_REQUISITE), "Unit" },
{ "RequisiteOverridable", config_parse_deps, UINT_TO_PTR(UNIT_REQUISITE_OVERRIDABLE), "Unit" },
{ "Wants", config_parse_deps, UINT_TO_PTR(UNIT_WANTS), "Unit" },
{ "BindTo", config_parse_deps, UINT_TO_PTR(UNIT_BIND_TO), "Unit" },
{ "Conflicts", config_parse_deps, UINT_TO_PTR(UNIT_CONFLICTS), "Unit" },
{ "Before", config_parse_deps, UINT_TO_PTR(UNIT_BEFORE), "Unit" },
{ "After", config_parse_deps, UINT_TO_PTR(UNIT_AFTER), "Unit" },
{ "OnFailure", config_parse_deps, UINT_TO_PTR(UNIT_ON_FAILURE), "Unit" },
{ "StopWhenUnneeded", config_parse_bool, &u->meta.stop_when_unneeded, "Unit" },
{ "RefuseManualStart", config_parse_bool, &u->meta.refuse_manual_start, "Unit" },
{ "RefuseManualStop", config_parse_bool, &u->meta.refuse_manual_stop, "Unit" },
{ "AllowIsolate", config_parse_bool, &u->meta.allow_isolate, "Unit" },
{ "DefaultDependencies", config_parse_bool, &u->meta.default_dependencies, "Unit" },
{ "JobTimeoutSec", config_parse_usec, &u->meta.job_timeout, "Unit" },
{ "ConditionPathExists", config_parse_condition_path, u, "Unit" },
{ "ConditionDirectoryNotEmpty", config_parse_condition_path, u, "Unit" },
{ "ConditionKernelCommandLine", config_parse_condition_kernel, u, "Unit" },
{ "ConditionVirtualization",config_parse_condition_virt, u, "Unit" },
{ "ConditionNull", config_parse_condition_null, u, "Unit" },
{ "Names", config_parse_names, 0, u, "Unit" },
{ "Description", config_parse_string_printf, 0, &u->meta.description, "Unit" },
{ "Requires", config_parse_deps, 0, UINT_TO_PTR(UNIT_REQUIRES), "Unit" },
{ "RequiresOverridable", config_parse_deps, 0, UINT_TO_PTR(UNIT_REQUIRES_OVERRIDABLE), "Unit" },
{ "Requisite", config_parse_deps, 0, UINT_TO_PTR(UNIT_REQUISITE), "Unit" },
{ "RequisiteOverridable", config_parse_deps, 0, UINT_TO_PTR(UNIT_REQUISITE_OVERRIDABLE), "Unit" },
{ "Wants", config_parse_deps, 0, UINT_TO_PTR(UNIT_WANTS), "Unit" },
{ "BindTo", config_parse_deps, 0, UINT_TO_PTR(UNIT_BIND_TO), "Unit" },
{ "Conflicts", config_parse_deps, 0, UINT_TO_PTR(UNIT_CONFLICTS), "Unit" },
{ "Before", config_parse_deps, 0, UINT_TO_PTR(UNIT_BEFORE), "Unit" },
{ "After", config_parse_deps, 0, UINT_TO_PTR(UNIT_AFTER), "Unit" },
{ "OnFailure", config_parse_deps, 0, UINT_TO_PTR(UNIT_ON_FAILURE), "Unit" },
{ "StopWhenUnneeded", config_parse_bool, 0, &u->meta.stop_when_unneeded, "Unit" },
{ "RefuseManualStart", config_parse_bool, 0, &u->meta.refuse_manual_start, "Unit" },
{ "RefuseManualStop", config_parse_bool, 0, &u->meta.refuse_manual_stop, "Unit" },
{ "AllowIsolate", config_parse_bool, 0, &u->meta.allow_isolate, "Unit" },
{ "DefaultDependencies", config_parse_bool, 0, &u->meta.default_dependencies, "Unit" },
{ "JobTimeoutSec", config_parse_usec, 0, &u->meta.job_timeout, "Unit" },
{ "ConditionPathExists", config_parse_condition_path, CONDITION_PATH_EXISTS, u, "Unit" },
{ "ConditionPathIsDirectory", config_parse_condition_path, CONDITION_PATH_IS_DIRECTORY, u, "Unit" },
{ "ConditionDirectoryNotEmpty", config_parse_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, u, "Unit" },
{ "ConditionKernelCommandLine", config_parse_condition_string, CONDITION_KERNEL_COMMAND_LINE, u, "Unit" },
{ "ConditionVirtualization", config_parse_condition_string, CONDITION_VIRTUALIZATION, u, "Unit" },
{ "ConditionSecurity", config_parse_condition_string, CONDITION_SECURITY, u, "Unit" },
{ "ConditionNull", config_parse_condition_null, 0, u, "Unit" },
{ "PIDFile", config_parse_path, &u->service.pid_file, "Service" },
{ "ExecStartPre", config_parse_exec, u->service.exec_command+SERVICE_EXEC_START_PRE, "Service" },
{ "ExecStart", config_parse_exec, u->service.exec_command+SERVICE_EXEC_START, "Service" },
{ "ExecStartPost", config_parse_exec, u->service.exec_command+SERVICE_EXEC_START_POST, "Service" },
{ "ExecReload", config_parse_exec, u->service.exec_command+SERVICE_EXEC_RELOAD, "Service" },
{ "ExecStop", config_parse_exec, u->service.exec_command+SERVICE_EXEC_STOP, "Service" },
{ "ExecStopPost", config_parse_exec, u->service.exec_command+SERVICE_EXEC_STOP_POST, "Service" },
{ "RestartSec", config_parse_usec, &u->service.restart_usec, "Service" },
{ "TimeoutSec", config_parse_usec, &u->service.timeout_usec, "Service" },
{ "Type", config_parse_service_type, &u->service.type, "Service" },
{ "Restart", config_parse_service_restart, &u->service.restart, "Service" },
{ "PermissionsStartOnly", config_parse_bool, &u->service.permissions_start_only, "Service" },
{ "RootDirectoryStartOnly", config_parse_bool, &u->service.root_directory_start_only, "Service" },
{ "RemainAfterExit", config_parse_bool, &u->service.remain_after_exit, "Service" },
{ "GuessMainPID", config_parse_bool, &u->service.guess_main_pid, "Service" },
{ "PIDFile", config_parse_path, 0, &u->service.pid_file, "Service" },
{ "ExecStartPre", config_parse_exec, 0, u->service.exec_command+SERVICE_EXEC_START_PRE, "Service" },
{ "ExecStart", config_parse_exec, 0, u->service.exec_command+SERVICE_EXEC_START, "Service" },
{ "ExecStartPost", config_parse_exec, 0, u->service.exec_command+SERVICE_EXEC_START_POST, "Service" },
{ "ExecReload", config_parse_exec, 0, u->service.exec_command+SERVICE_EXEC_RELOAD, "Service" },
{ "ExecStop", config_parse_exec, 0, u->service.exec_command+SERVICE_EXEC_STOP, "Service" },
{ "ExecStopPost", config_parse_exec, 0, u->service.exec_command+SERVICE_EXEC_STOP_POST, "Service" },
{ "RestartSec", config_parse_usec, 0, &u->service.restart_usec, "Service" },
{ "TimeoutSec", config_parse_usec, 0, &u->service.timeout_usec, "Service" },
{ "Type", config_parse_service_type, 0, &u->service.type, "Service" },
{ "Restart", config_parse_service_restart, 0, &u->service.restart, "Service" },
{ "PermissionsStartOnly", config_parse_bool, 0, &u->service.permissions_start_only, "Service" },
{ "RootDirectoryStartOnly", config_parse_bool, 0, &u->service.root_directory_start_only, "Service" },
{ "RemainAfterExit", config_parse_bool, 0, &u->service.remain_after_exit, "Service" },
{ "GuessMainPID", config_parse_bool, 0, &u->service.guess_main_pid, "Service" },
#ifdef HAVE_SYSV_COMPAT
{ "SysVStartPriority", config_parse_sysv_priority, &u->service.sysv_start_priority, "Service" },
{ "SysVStartPriority", config_parse_sysv_priority, 0, &u->service.sysv_start_priority, "Service" },
#else
{ "SysVStartPriority", config_parse_warn_compat, NULL, "Service" },
{ "SysVStartPriority", config_parse_warn_compat, 0, NULL, "Service" },
#endif
{ "NonBlocking", config_parse_bool, &u->service.exec_context.non_blocking, "Service" },
{ "BusName", config_parse_string_printf, &u->service.bus_name, "Service" },
{ "NotifyAccess", config_parse_notify_access, &u->service.notify_access, "Service" },
{ "Sockets", config_parse_service_sockets, &u->service, "Service" },
{ "FsckPassNo", config_parse_fsck_passno, &u->service.fsck_passno, "Service" },
{ "NonBlocking", config_parse_bool, 0, &u->service.exec_context.non_blocking, "Service" },
{ "BusName", config_parse_string_printf, 0, &u->service.bus_name, "Service" },
{ "NotifyAccess", config_parse_notify_access, 0, &u->service.notify_access, "Service" },
{ "Sockets", config_parse_service_sockets, 0, &u->service, "Service" },
{ "FsckPassNo", config_parse_fsck_passno, 0, &u->service.fsck_passno, "Service" },
EXEC_CONTEXT_CONFIG_ITEMS(u->service.exec_context, "Service"),
{ "ListenStream", config_parse_listen, &u->socket, "Socket" },
{ "ListenDatagram", config_parse_listen, &u->socket, "Socket" },
{ "ListenSequentialPacket", config_parse_listen, &u->socket, "Socket" },
{ "ListenFIFO", config_parse_listen, &u->socket, "Socket" },
{ "BindIPv6Only", config_parse_socket_bind, &u->socket, "Socket" },
{ "Backlog", config_parse_unsigned, &u->socket.backlog, "Socket" },
{ "BindToDevice", config_parse_bindtodevice, &u->socket, "Socket" },
{ "ExecStartPre", config_parse_exec, u->socket.exec_command+SOCKET_EXEC_START_PRE, "Socket" },
{ "ExecStartPost", config_parse_exec, u->socket.exec_command+SOCKET_EXEC_START_POST, "Socket" },
{ "ExecStopPre", config_parse_exec, u->socket.exec_command+SOCKET_EXEC_STOP_PRE, "Socket" },
{ "ExecStopPost", config_parse_exec, u->socket.exec_command+SOCKET_EXEC_STOP_POST, "Socket" },
{ "TimeoutSec", config_parse_usec, &u->socket.timeout_usec, "Socket" },
{ "DirectoryMode", config_parse_mode, &u->socket.directory_mode, "Socket" },
{ "SocketMode", config_parse_mode, &u->socket.socket_mode, "Socket" },
{ "Accept", config_parse_bool, &u->socket.accept, "Socket" },
{ "MaxConnections", config_parse_unsigned, &u->socket.max_connections, "Socket" },
{ "KeepAlive", config_parse_bool, &u->socket.keep_alive, "Socket" },
{ "Priority", config_parse_int, &u->socket.priority, "Socket" },
{ "ReceiveBuffer", config_parse_size, &u->socket.receive_buffer, "Socket" },
{ "SendBuffer", config_parse_size, &u->socket.send_buffer, "Socket" },
{ "IPTOS", config_parse_ip_tos, &u->socket.ip_tos, "Socket" },
{ "IPTTL", config_parse_int, &u->socket.ip_ttl, "Socket" },
{ "Mark", config_parse_int, &u->socket.mark, "Socket" },
{ "PipeSize", config_parse_size, &u->socket.pipe_size, "Socket" },
{ "FreeBind", config_parse_bool, &u->socket.free_bind, "Socket" },
{ "TCPCongestion", config_parse_string, &u->socket.tcp_congestion, "Socket" },
{ "Service", config_parse_socket_service, &u->socket, "Socket" },
{ "ListenStream", config_parse_listen, 0, &u->socket, "Socket" },
{ "ListenDatagram", config_parse_listen, 0, &u->socket, "Socket" },
{ "ListenSequentialPacket", config_parse_listen, 0, &u->socket, "Socket" },
{ "ListenFIFO", config_parse_listen, 0, &u->socket, "Socket" },
{ "BindIPv6Only", config_parse_socket_bind, 0, &u->socket, "Socket" },
{ "Backlog", config_parse_unsigned, 0, &u->socket.backlog, "Socket" },
{ "BindToDevice", config_parse_bindtodevice, 0, &u->socket, "Socket" },
{ "ExecStartPre", config_parse_exec, 0, u->socket.exec_command+SOCKET_EXEC_START_PRE, "Socket" },
{ "ExecStartPost", config_parse_exec, 0, u->socket.exec_command+SOCKET_EXEC_START_POST, "Socket" },
{ "ExecStopPre", config_parse_exec, 0, u->socket.exec_command+SOCKET_EXEC_STOP_PRE, "Socket" },
{ "ExecStopPost", config_parse_exec, 0, u->socket.exec_command+SOCKET_EXEC_STOP_POST, "Socket" },
{ "TimeoutSec", config_parse_usec, 0, &u->socket.timeout_usec, "Socket" },
{ "DirectoryMode", config_parse_mode, 0, &u->socket.directory_mode, "Socket" },
{ "SocketMode", config_parse_mode, 0, &u->socket.socket_mode, "Socket" },
{ "Accept", config_parse_bool, 0, &u->socket.accept, "Socket" },
{ "MaxConnections", config_parse_unsigned, 0, &u->socket.max_connections, "Socket" },
{ "KeepAlive", config_parse_bool, 0, &u->socket.keep_alive, "Socket" },
{ "Priority", config_parse_int, 0, &u->socket.priority, "Socket" },
{ "ReceiveBuffer", config_parse_size, 0, &u->socket.receive_buffer, "Socket" },
{ "SendBuffer", config_parse_size, 0, &u->socket.send_buffer, "Socket" },
{ "IPTOS", config_parse_ip_tos, 0, &u->socket.ip_tos, "Socket" },
{ "IPTTL", config_parse_int, 0, &u->socket.ip_ttl, "Socket" },
{ "Mark", config_parse_int, 0, &u->socket.mark, "Socket" },
{ "PipeSize", config_parse_size, 0, &u->socket.pipe_size, "Socket" },
{ "FreeBind", config_parse_bool, 0, &u->socket.free_bind, "Socket" },
{ "TCPCongestion", config_parse_string, 0, &u->socket.tcp_congestion, "Socket" },
{ "Service", config_parse_socket_service, 0, &u->socket, "Socket" },
EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
{ "What", config_parse_string, &u->mount.parameters_fragment.what, "Mount" },
{ "Where", config_parse_path, &u->mount.where, "Mount" },
{ "Options", config_parse_string, &u->mount.parameters_fragment.options, "Mount" },
{ "Type", config_parse_string, &u->mount.parameters_fragment.fstype, "Mount" },
{ "TimeoutSec", config_parse_usec, &u->mount.timeout_usec, "Mount" },
{ "DirectoryMode", config_parse_mode, &u->mount.directory_mode, "Mount" },
{ "What", config_parse_string, 0, &u->mount.parameters_fragment.what, "Mount" },
{ "Where", config_parse_path, 0, &u->mount.where, "Mount" },
{ "Options", config_parse_string, 0, &u->mount.parameters_fragment.options, "Mount" },
{ "Type", config_parse_string, 0, &u->mount.parameters_fragment.fstype, "Mount" },
{ "TimeoutSec", config_parse_usec, 0, &u->mount.timeout_usec, "Mount" },
{ "DirectoryMode", config_parse_mode, 0, &u->mount.directory_mode, "Mount" },
EXEC_CONTEXT_CONFIG_ITEMS(u->mount.exec_context, "Mount"),
{ "Where", config_parse_path, &u->automount.where, "Automount" },
{ "DirectoryMode", config_parse_mode, &u->automount.directory_mode, "Automount" },
{ "Where", config_parse_path, 0, &u->automount.where, "Automount" },
{ "DirectoryMode", config_parse_mode, 0, &u->automount.directory_mode, "Automount" },
{ "What", config_parse_path, &u->swap.parameters_fragment.what, "Swap" },
{ "Priority", config_parse_int, &u->swap.parameters_fragment.priority, "Swap" },
{ "TimeoutSec", config_parse_usec, &u->swap.timeout_usec, "Swap" },
{ "What", config_parse_path, 0, &u->swap.parameters_fragment.what, "Swap" },
{ "Priority", config_parse_int, 0, &u->swap.parameters_fragment.priority, "Swap" },
{ "TimeoutSec", config_parse_usec, 0, &u->swap.timeout_usec, "Swap" },
EXEC_CONTEXT_CONFIG_ITEMS(u->swap.exec_context, "Swap"),
{ "OnActiveSec", config_parse_timer, &u->timer, "Timer" },
{ "OnBootSec", config_parse_timer, &u->timer, "Timer" },
{ "OnStartupSec", config_parse_timer, &u->timer, "Timer" },
{ "OnUnitActiveSec", config_parse_timer, &u->timer, "Timer" },
{ "OnUnitInactiveSec", config_parse_timer, &u->timer, "Timer" },
{ "Unit", config_parse_timer_unit, &u->timer, "Timer" },
{ "OnActiveSec", config_parse_timer, 0, &u->timer, "Timer" },
{ "OnBootSec", config_parse_timer, 0, &u->timer, "Timer" },
{ "OnStartupSec", config_parse_timer, 0, &u->timer, "Timer" },
{ "OnUnitActiveSec", config_parse_timer, 0, &u->timer, "Timer" },
{ "OnUnitInactiveSec", config_parse_timer, 0, &u->timer, "Timer" },
{ "Unit", config_parse_timer_unit, 0, &u->timer, "Timer" },
{ "PathExists", config_parse_path_spec, &u->path, "Path" },
{ "PathChanged", config_parse_path_spec, &u->path, "Path" },
{ "DirectoryNotEmpty", config_parse_path_spec, &u->path, "Path" },
{ "Unit", config_parse_path_unit, &u->path, "Path" },
{ "PathExists", config_parse_path_spec, 0, &u->path, "Path" },
{ "PathChanged", config_parse_path_spec, 0, &u->path, "Path" },
{ "DirectoryNotEmpty", config_parse_path_spec, 0, &u->path, "Path" },
{ "Unit", config_parse_path_unit, 0, &u->path, "Path" },
/* The [Install] section is ignored here. */
{ "Alias", NULL, NULL, "Install" },
{ "WantedBy", NULL, NULL, "Install" },
{ "Also", NULL, NULL, "Install" },
{ "Alias", NULL, 0, NULL, "Install" },
{ "WantedBy", NULL, 0, NULL, "Install" },
{ "Also", NULL, 0, NULL, "Install" },
{ NULL, NULL, NULL, NULL }
{ NULL, NULL, 0, NULL, NULL }
};
#undef EXEC_CONTEXT_CONFIG_ITEMS

View File

@ -54,7 +54,7 @@ static const char * const variable_names[_VARIABLE_MAX] = {
[VARIABLE_LC_TIME] = "LC_TIME",
[VARIABLE_LC_COLLATE] = "LC_COLLATE",
[VARIABLE_LC_MONETARY] = "LC_MONETARY",
[VARIABLE_LC_MESSAGES] = "LC_MESSAGE",
[VARIABLE_LC_MESSAGES] = "LC_MESSAGES",
[VARIABLE_LC_PAPER] = "LC_PAPER",
[VARIABLE_LC_NAME] = "LC_NAME",
[VARIABLE_LC_ADDRESS] = "LC_ADDRESS",
@ -65,32 +65,33 @@ static const char * const variable_names[_VARIABLE_MAX] = {
int locale_setup(void) {
char *variables[_VARIABLE_MAX];
int r, i;
int r = 0, i;
zero(variables);
if ((r = parse_env_file("/proc/cmdline", WHITESPACE,
if (detect_container(NULL) <= 0)
if ((r = parse_env_file("/proc/cmdline", WHITESPACE,
#ifdef TARGET_FEDORA
"LANG", &variables[VARIABLE_LANG],
"LANG", &variables[VARIABLE_LANG],
#endif
"locale.LANG", &variables[VARIABLE_LANG],
"locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
"locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
"locale.LC_TIME", &variables[VARIABLE_LC_TIME],
"locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
"locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
"locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
"locale.LC_PAPER", &variables[VARIABLE_LC_PAPER],
"locale.LC_NAME", &variables[VARIABLE_LC_NAME],
"locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
"locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
"locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
"locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
NULL)) < 0) {
"locale.LANG", &variables[VARIABLE_LANG],
"locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
"locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
"locale.LC_TIME", &variables[VARIABLE_LC_TIME],
"locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
"locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
"locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
"locale.LC_PAPER", &variables[VARIABLE_LC_PAPER],
"locale.LC_NAME", &variables[VARIABLE_LC_NAME],
"locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
"locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
"locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
"locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
NULL)) < 0) {
if (r != -ENOENT)
log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
}
if (r != -ENOENT)
log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
}
/* Hmm, nothing set on the kernel cmd line? Then let's
* try /etc/locale.conf */
@ -138,7 +139,19 @@ int locale_setup(void) {
#elif defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU)
if (r <= 0 &&
(r = parse_env_file("/etc/default/locale", NEWLINE,
"LANG", &variables[VARIABLE_LANG],
"LANG", &variables[VARIABLE_LANG],
"LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
"LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
"LC_TIME", &variables[VARIABLE_LC_TIME],
"LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
"LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
"LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
"LC_PAPER", &variables[VARIABLE_LC_PAPER],
"LC_NAME", &variables[VARIABLE_LC_NAME],
"LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
"LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
"LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
"LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
NULL)) < 0) {
if (r != -ENOENT)

View File

@ -289,7 +289,7 @@ static int write_to_syslog(
if (syslog_fd < 0)
return 0;
snprintf(header_priority, sizeof(header_priority), "<%i>", LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(level)));
snprintf(header_priority, sizeof(header_priority), "<%i>", level);
char_array_0(header_priority);
t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
@ -346,7 +346,7 @@ static int write_to_kmsg(
if (kmsg_fd < 0)
return 0;
snprintf(header_priority, sizeof(header_priority), "<%i>", LOG_PRI(level));
snprintf(header_priority, sizeof(header_priority), "<%i>", level);
char_array_0(header_priority);
snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
@ -377,6 +377,10 @@ static int log_dispatch(
if (log_target == LOG_TARGET_NULL)
return 0;
/* Patch in LOG_DAEMON facility if necessary */
if ((level & LOG_FACMASK) == 0)
level = LOG_DAEMON | LOG_PRI(level);
do {
char *e;
int k = 0;

View File

@ -104,20 +104,16 @@ static int stream_log(Stream *s, char *p, usec_t ts) {
priority = s->priority;
if (s->prefix &&
p[0] == '<' &&
p[1] >= '0' && p[1] <= '7' &&
p[2] == '>') {
/* Detected priority prefix */
priority = LOG_MAKEPRI(LOG_FAC(priority), (p[1] - '0'));
p += 3;
}
if (s->prefix)
parse_syslog_priority(&p, &priority);
if (*p == 0)
return 0;
/* Patch in LOG_USER facility if necessary */
if ((priority & LOG_FACMASK) == 0)
priority = LOG_USER | LOG_PRI(priority);
/*
* The format glibc uses to talk to the syslog daemon is:
*
@ -130,8 +126,7 @@ static int stream_log(Stream *s, char *p, usec_t ts) {
* We extend the latter to include the process name and pid.
*/
snprintf(header_priority, sizeof(header_priority), "<%i>",
s->target == STREAM_SYSLOG ? priority : LOG_PRI(priority));
snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
char_array_0(header_priority);
if (s->target == STREAM_SYSLOG) {

View File

@ -265,7 +265,7 @@ int loopback_setup(void) {
finish:
if (r < 0)
log_error("Failed to configure loopback device: %s", strerror(-r));
log_warning("Failed to configure loopback device: %s", strerror(-r));
if (fd >= 0)
close_nointr_nofail(fd);

View File

@ -142,20 +142,20 @@ int machine_id_setup(void) {
fd = -1;
/* Hmm, we couldn't write it? So let's write it to
* /dev/.systemd/machine-id as a replacement */
* /run/systemd/machine-id as a replacement */
mkdir_p("/dev/.systemd", 0755);
mkdir_p("/run/systemd", 0755);
if ((r = write_one_line_file("/dev/.systemd/machine-id", id)) < 0) {
log_error("Cannot write /dev/.systemd/machine-id: %s", strerror(-r));
if ((r = write_one_line_file("/run/systemd/machine-id", id)) < 0) {
log_error("Cannot write /run/systemd/machine-id: %s", strerror(-r));
unlink("/dev/.systemd/machine-id");
unlink("/run/systemd/machine-id");
goto finish;
}
/* And now, let's mount it over */
r = mount("/dev/.systemd/machine-id", "/etc/machine-id", "bind", MS_BIND|MS_RDONLY, NULL) < 0 ? -errno : 0;
unlink("/dev/.systemd/machine-id");
r = mount("/run/systemd/machine-id", "/etc/machine-id", "bind", MS_BIND|MS_RDONLY, NULL) < 0 ? -errno : 0;
unlink("/run/systemd/machine-id");
if (r < 0)
log_error("Failed to mount /etc/machine-id: %s", strerror(-r));

View File

@ -27,8 +27,6 @@
#include <sys/uio.h>
#include <inttypes.h>
#define PAGE_SIZE 4096
#define _printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
#define _sentinel_ __attribute__ ((sentinel))
#define _noreturn_ __attribute__((noreturn))
@ -51,12 +49,9 @@
#define STRINGIFY(x) XSTRINGIFY(x)
/* Rounds up */
static inline size_t ALIGN(size_t l) {
return ((l + sizeof(void*) - 1) & ~(sizeof(void*) - 1));
}
static inline size_t PAGE_ALIGN(size_t l) {
return ((l + PAGE_SIZE - 1) & ~(PAGE_SIZE -1));
#define ALIGN(l) ALIGN_TO((l), sizeof(void*))
static inline size_t ALIGN_TO(size_t l, size_t ali) {
return ((l + ali - 1) & ~(ali - 1));
}
#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))

View File

@ -51,6 +51,7 @@
#include "label.h"
#include "build.h"
#include "strv.h"
#include "def.h"
static enum {
ACTION_RUN,
@ -226,6 +227,7 @@ static int parse_proc_cmdline_word(const char *word) {
static const char * const rlmap[] = {
"emergency", SPECIAL_EMERGENCY_TARGET,
"-b", SPECIAL_EMERGENCY_TARGET,
"single", SPECIAL_RESCUE_TARGET,
"-s", SPECIAL_RESCUE_TARGET,
"s", SPECIAL_RESCUE_TARGET,
@ -371,6 +373,7 @@ static int config_parse_level(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -388,6 +391,7 @@ static int config_parse_target(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -405,6 +409,7 @@ static int config_parse_color(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -422,6 +427,7 @@ static int config_parse_location(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -439,6 +445,7 @@ static int config_parse_cpu_affinity(
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
@ -492,24 +499,24 @@ static DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "F
static int parse_config_file(void) {
const ConfigItem items[] = {
{ "LogLevel", config_parse_level, NULL, "Manager" },
{ "LogTarget", config_parse_target, NULL, "Manager" },
{ "LogColor", config_parse_color, NULL, "Manager" },
{ "LogLocation", config_parse_location, NULL, "Manager" },
{ "DumpCore", config_parse_bool, &arg_dump_core, "Manager" },
{ "CrashShell", config_parse_bool, &arg_crash_shell, "Manager" },
{ "ShowStatus", config_parse_bool, &arg_show_status, "Manager" },
{ "LogLevel", config_parse_level, 0, NULL, "Manager" },
{ "LogTarget", config_parse_target, 0, NULL, "Manager" },
{ "LogColor", config_parse_color, 0, NULL, "Manager" },
{ "LogLocation", config_parse_location, 0, NULL, "Manager" },
{ "DumpCore", config_parse_bool, 0, &arg_dump_core, "Manager" },
{ "CrashShell", config_parse_bool, 0, &arg_crash_shell, "Manager" },
{ "ShowStatus", config_parse_bool, 0, &arg_show_status, "Manager" },
#ifdef HAVE_SYSV_COMPAT
{ "SysVConsole", config_parse_bool, &arg_sysv_console, "Manager" },
{ "SysVConsole", config_parse_bool, 0, &arg_sysv_console, "Manager" },
#endif
{ "CrashChVT", config_parse_int, &arg_crash_chvt, "Manager" },
{ "CPUAffinity", config_parse_cpu_affinity, NULL, "Manager" },
{ "MountAuto", config_parse_bool, &arg_mount_auto, "Manager" },
{ "SwapAuto", config_parse_bool, &arg_swap_auto, "Manager" },
{ "DefaultControllers", config_parse_strv, &arg_default_controllers, "Manager" },
{ "DefaultStandardOutput", config_parse_output, &arg_default_std_output, "Manager" },
{ "DefaultStandardError", config_parse_output, &arg_default_std_error, "Manager" },
{ NULL, NULL, NULL, NULL }
{ "CrashChVT", config_parse_int, 0, &arg_crash_chvt, "Manager" },
{ "CPUAffinity", config_parse_cpu_affinity, 0, NULL, "Manager" },
{ "MountAuto", config_parse_bool, 0, &arg_mount_auto, "Manager" },
{ "SwapAuto", config_parse_bool, 0, &arg_swap_auto, "Manager" },
{ "DefaultControllers", config_parse_strv, 0, &arg_default_controllers, "Manager" },
{ "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output, "Manager" },
{ "DefaultStandardError", config_parse_output, 0, &arg_default_std_error, "Manager" },
{ NULL, NULL, 0, NULL, NULL }
};
static const char * const sections[] = {
@ -544,6 +551,11 @@ static int parse_proc_cmdline(void) {
int r;
size_t l;
/* Don't read /proc/cmdline if we are in a container, since
* that is only relevant for the host system */
if (detect_container(NULL) > 0)
return 0;
if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
return 0;
@ -624,7 +636,10 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 1);
assert(argv);
while ((c = getopt_long(argc, argv, "hD", options, NULL)) >= 0)
if (getpid() == 1)
opterr = 0;
while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0)
switch (c) {
@ -800,23 +815,48 @@ static int parse_argv(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
break;
case '?':
return -EINVAL;
case 'b':
case 's':
case 'z':
/* Just to eat away the sysvinit kernel
* cmdline args without getopt() error
* messages that we'll parse in
* parse_proc_cmdline_word() or ignore. */
case '?':
default:
log_error("Unknown option code %c", c);
return -EINVAL;
if (getpid() != 1) {
log_error("Unknown option code %c", c);
return -EINVAL;
}
break;
}
/* PID 1 will get the kernel arguments as parameters, which we
* ignore and unconditionally read from
* /proc/cmdline. However, we need to ignore those arguments
* here. */
if (arg_running_as != MANAGER_SYSTEM && optind < argc) {
if (optind < argc && getpid() != 1) {
/* Hmm, when we aren't run as init system
* let's complain about excess arguments */
log_error("Excess arguments.");
return -EINVAL;
}
if (detect_container(NULL) > 0) {
char **a;
/* All /proc/cmdline arguments the kernel didn't
* understand it passed to us. We're not really
* interested in that usually since /proc/cmdline is
* more interesting and complete. With one exception:
* if we are run in a container /proc/cmdline is not
* relevant for the container, hence we rely on argv[]
* instead. */
for (a = argv; a < argv + argc; a++)
if ((r = parse_proc_cmdline_word(*a)) < 0)
return r;
}
return 0;
}
@ -942,20 +982,10 @@ static void test_mtab(void) {
}
static void test_usr(void) {
bool separate = false;
/* Check that /usr is not a separate fs */
if (path_is_mount_point("/usr") > 0)
separate = true;
/* This check won't work usually during boot, since /usr is
* probably not mounted yet, hence let's add a second
* check. We just check whether /usr is an empty directory. */
if (dir_is_empty("/usr") > 0)
separate = true;
if (!separate)
if (dir_is_empty("/usr") <= 0)
return;
log_warning("/usr appears to be on a different file system than /. This is not supported anymore. "
@ -963,6 +993,20 @@ static void test_usr(void) {
"Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information.");
}
static void test_cgroups(void) {
if (access("/proc/cgroups", F_OK) >= 0)
return;
log_warning("CONFIG_CGROUPS was not set when your kernel was compiled. "
"Systems without control groups are not supported. "
"We will now sleep for 10s, and then continue boot-up. "
"Expect breakage and please do not file bugs. "
"Instead fix your kernel and enable CONFIG_CGROUPS." );
sleep(10);
}
int main(int argc, char *argv[]) {
Manager *m = NULL;
int r, retval = EXIT_FAILURE;
@ -996,7 +1040,7 @@ int main(int argc, char *argv[]) {
if (getpid() == 1) {
arg_running_as = MANAGER_SYSTEM;
log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_CONSOLE : LOG_TARGET_SYSLOG_OR_KMSG);
/* This might actually not return, but cause a
* reexecution */
@ -1042,10 +1086,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
/* If Plymouth is being run make sure we show the status, so
* that there's something nice to see when people press Esc */
if (access("/dev/.systemd/plymouth", F_OK) >= 0)
arg_show_status = true;
if (arg_running_as == MANAGER_SYSTEM &&
arg_action == ACTION_RUN &&
running_in_chroot() > 0) {
log_error("Cannot be run in a chroot() environment.");
goto finish;
}
if (arg_action == ACTION_HELP) {
retval = help();
@ -1086,6 +1132,9 @@ int main(int argc, char *argv[]) {
* kernel that don't really make sense for us. */
unsetenv("HOME");
unsetenv("TERM");
/* All other variables are left as is, so that clients
* can still read them via /proc/1/environ */
}
/* Move out of the way, so that we won't block unmounts */
@ -1123,7 +1172,7 @@ int main(int argc, char *argv[]) {
if (arg_running_as == MANAGER_SYSTEM && !serialization) {
locale_setup();
if (arg_show_status)
if (arg_show_status || plymouth_running())
status_welcome();
kmod_setup();
@ -1131,10 +1180,9 @@ int main(int argc, char *argv[]) {
machine_id_setup();
loopback_setup();
mkdir_p("/dev/.systemd/ask-password/", 0755);
test_mtab();
test_usr();
test_cgroups();
}
if ((r = manager_new(arg_running_as, &m)) < 0) {

View File

@ -66,7 +66,8 @@
#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
/* Where clients shall send notification messages to */
#define NOTIFY_SOCKET "/org/freedesktop/systemd1/notify"
#define NOTIFY_SOCKET_SYSTEM "/run/systemd/notify"
#define NOTIFY_SOCKET_USER "@/org/freedesktop/systemd1/notify"
static int manager_setup_notify(Manager *m) {
union {
@ -88,9 +89,14 @@ static int manager_setup_notify(Manager *m) {
sa.sa.sa_family = AF_UNIX;
if (getpid() != 1)
snprintf(sa.un.sun_path+1, sizeof(sa.un.sun_path)-1, NOTIFY_SOCKET "/%llu", random_ull());
else
strncpy(sa.un.sun_path+1, NOTIFY_SOCKET, sizeof(sa.un.sun_path)-1);
snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET_USER "/%llu", random_ull());
else {
unlink(NOTIFY_SOCKET_SYSTEM);
strncpy(sa.un.sun_path, NOTIFY_SOCKET_SYSTEM, sizeof(sa.un.sun_path));
}
if (sa.un.sun_path[0] == '@')
sa.un.sun_path[0] = 0;
if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
log_error("bind() failed: %m");
@ -109,7 +115,10 @@ static int manager_setup_notify(Manager *m) {
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0)
return -errno;
if (!(m->notify_socket = strdup(sa.un.sun_path+1)))
if (sa.un.sun_path[0] == 0)
sa.un.sun_path[0] = '@';
if (!(m->notify_socket = strdup(sa.un.sun_path)))
return -ENOMEM;
log_debug("Using notification socket %s", m->notify_socket);
@ -118,7 +127,7 @@ static int manager_setup_notify(Manager *m) {
}
static int enable_special_signals(Manager *m) {
char fd;
int fd;
assert(m);
@ -269,6 +278,8 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) {
log_error("Failed to connect to audit log: %m");
#endif
m->taint_usr = dir_is_empty("/usr") > 0;
*_m = m;
return 0;
@ -1412,7 +1423,8 @@ static int transaction_add_job_and_dependencies(
bool matters,
bool override,
bool conflicts,
bool ignore_deps,
bool ignore_requirements,
bool ignore_order,
DBusError *e,
Job **_ret) {
Job *ret;
@ -1460,20 +1472,20 @@ static int transaction_add_job_and_dependencies(
if (!(ret = transaction_add_one_job(m, type, unit, override, &is_new)))
return -ENOMEM;
ret->ignore_deps = ret->ignore_deps || ignore_deps;
ret->ignore_order = ret->ignore_order || ignore_order;
/* Then, add a link to the job. */
if (!job_dependency_new(by, ret, matters, conflicts))
return -ENOMEM;
if (is_new && !ignore_deps) {
if (is_new && !ignore_requirements) {
Set *following;
/* If we are following some other unit, make sure we
* add all dependencies of everybody following. */
if (unit_following_set(ret->unit, &following) > 0) {
SET_FOREACH(dep, following, i)
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, false, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, false, override, false, false, ignore_order, e, NULL)) < 0) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
if (e)
@ -1486,7 +1498,7 @@ static int transaction_add_job_and_dependencies(
/* Finally, recursively add in all dependencies. */
if (type == JOB_START || type == JOB_RELOAD_OR_START) {
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRES], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, override, false, false, ignore_order, e, NULL)) < 0) {
if (r != -EBADR)
goto fail;
@ -1495,7 +1507,7 @@ static int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_BIND_TO], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, override, false, false, ignore_order, e, NULL)) < 0) {
if (r != -EBADR)
goto fail;
@ -1505,7 +1517,7 @@ static int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !override, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !override, override, false, false, ignore_order, e, NULL)) < 0) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
if (e)
@ -1513,7 +1525,7 @@ static int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_WANTS], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, false, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, false, false, false, ignore_order, e, NULL)) < 0) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
if (e)
@ -1521,7 +1533,7 @@ static int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUISITE], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, false, ignore_order, e, NULL)) < 0) {
if (r != -EBADR)
goto fail;
@ -1531,7 +1543,7 @@ static int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, false, ignore_order, e, NULL)) < 0) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
if (e)
@ -1539,7 +1551,7 @@ static int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_CONFLICTS], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, true, override, true, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, true, override, true, false, ignore_order, e, NULL)) < 0) {
if (r != -EBADR)
goto fail;
@ -1549,7 +1561,7 @@ static int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_CONFLICTED_BY], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, false, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, false, override, false, false, ignore_order, e, NULL)) < 0) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
if (e)
@ -1559,7 +1571,7 @@ static int transaction_add_job_and_dependencies(
} else if (type == JOB_STOP || type == JOB_RESTART || type == JOB_TRY_RESTART) {
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRED_BY], i)
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, override, false, false, ignore_order, e, NULL)) < 0) {
if (r != -EBADR)
goto fail;
@ -1569,7 +1581,7 @@ static int transaction_add_job_and_dependencies(
}
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_BOUND_BY], i)
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, override, false, false, e, NULL)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, override, false, false, ignore_order, e, NULL)) < 0) {
if (r != -EBADR)
goto fail;
@ -1616,7 +1628,7 @@ static int transaction_add_isolate_jobs(Manager *m) {
if (hashmap_get(m->transaction_jobs, u))
continue;
if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, u, NULL, true, false, false, false, NULL, NULL)) < 0)
if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, u, NULL, true, false, false, false, false, NULL, NULL)) < 0)
log_warning("Cannot add isolate job for unit %s, ignoring: %s", u->meta.id, strerror(-r));
}
@ -1644,7 +1656,9 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove
log_debug("Trying to enqueue job %s/%s/%s", unit->meta.id, job_type_to_string(type), job_mode_to_string(mode));
if ((r = transaction_add_job_and_dependencies(m, type, unit, NULL, true, override, false, mode == JOB_IGNORE_DEPENDENCIES, e, &ret)) < 0) {
if ((r = transaction_add_job_and_dependencies(m, type, unit, NULL, true, override, false,
mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS,
mode == JOB_IGNORE_DEPENDENCIES, e, &ret)) < 0) {
transaction_abort(m);
return r;
}
@ -2059,7 +2073,17 @@ static int manager_process_signal_fd(Manager *m) {
return -errno;
}
log_debug("Received SIG%s", strna(signal_to_string(sfsi.ssi_signo)));
if (sfsi.ssi_pid > 0) {
char *p = NULL;
get_process_name(sfsi.ssi_pid, &p);
log_debug("Received SIG%s from PID %lu (%s).",
strna(signal_to_string(sfsi.ssi_signo)),
(unsigned long) sfsi.ssi_pid, strna(p));
free(p);
} else
log_debug("Received SIG%s.", strna(signal_to_string(sfsi.ssi_signo)));
switch (sfsi.ssi_signo) {
@ -2309,7 +2333,7 @@ static int process_event(Manager *m, struct epoll_event *ev) {
int manager_loop(Manager *m) {
int r;
RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 1000);
RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000);
assert(m);
m->exit_code = MANAGER_RUNNING;
@ -2434,13 +2458,30 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
if (m->n_deserializing > 0)
return;
if (m->running_as != MANAGER_SYSTEM)
return;
if (u->meta.type != UNIT_SERVICE)
return;
if (!(p = unit_name_to_prefix_and_instance(u->meta.id))) {
log_error("Failed to allocate unit name for audit message: %s", strerror(ENOMEM));
return;
}
if (audit_log_user_comm_message(m->audit_fd, type, "", p, NULL, NULL, NULL, success) < 0)
log_error("Failed to send audit message: %m");
if (audit_log_user_comm_message(m->audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
log_warning("Failed to send audit message: %m");
if (errno == EPERM) {
/* We aren't allowed to send audit messages?
* Then let's not retry again, to avoid
* spamming the user with the same and same
* messages over and over. */
audit_close(m->audit_fd);
m->audit_fd = -1;
}
}
free(p);
#endif
@ -2550,22 +2591,20 @@ void manager_dispatch_bus_query_pid_done(
}
int manager_open_serialization(Manager *m, FILE **_f) {
char *path;
char *path = NULL;
mode_t saved_umask;
int fd;
FILE *f;
assert(_f);
if (m->running_as == MANAGER_SYSTEM) {
mkdir_p("/dev/.systemd", 0755);
if (m->running_as == MANAGER_SYSTEM)
asprintf(&path, "/run/systemd/dump-%lu-XXXXXX", (unsigned long) getpid());
else
asprintf(&path, "/tmp/systemd-dump-%lu-XXXXXX", (unsigned long) getpid());
if (asprintf(&path, "/dev/.systemd/dump-%lu-XXXXXX", (unsigned long) getpid()) < 0)
return -ENOMEM;
} else {
if (asprintf(&path, "/tmp/systemd-dump-%lu-XXXXXX", (unsigned long) getpid()) < 0)
return -ENOMEM;
}
if (!path)
return -ENOMEM;
saved_umask = umask(0077);
fd = mkostemp(path, O_RDWR|O_CLOEXEC);
@ -2581,7 +2620,7 @@ int manager_open_serialization(Manager *m, FILE **_f) {
log_debug("Serializing state to %s", path);
free(path);
if (!(f = fdopen(fd, "w+")) < 0)
if (!(f = fdopen(fd, "w+")))
return -errno;
*_f = f;
@ -2817,7 +2856,8 @@ void manager_check_finished(Manager *m) {
dual_timestamp_get(&m->finish_timestamp);
if (m->running_as == MANAGER_SYSTEM) {
if (m->running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0) {
if (dual_timestamp_is_set(&m->initrd_timestamp)) {
log_info("Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
format_timespan(kernel, sizeof(kernel),
@ -2862,7 +2902,7 @@ void manager_run_generators(Manager *m) {
if (!m->generator_unit_path) {
char *p;
char system_path[] = "/dev/.systemd/generator-XXXXXX",
char system_path[] = "/run/systemd/generator-XXXXXX",
user_path[] = "/tmp/systemd-generator-XXXXXX";
if (!(p = mkdtemp(m->running_as == MANAGER_SYSTEM ? system_path : user_path))) {
@ -2938,6 +2978,47 @@ int manager_set_default_controllers(Manager *m, char **controllers) {
return 0;
}
void manager_recheck_syslog(Manager *m) {
Unit *u;
assert(m);
if (m->running_as != MANAGER_SYSTEM)
return;
if ((u = manager_get_unit(m, SPECIAL_SYSLOG_SOCKET))) {
SocketState state;
state = SOCKET(u)->state;
if (state != SOCKET_DEAD &&
state != SOCKET_FAILED &&
state != SOCKET_RUNNING) {
/* Hmm, the socket is not set up, or is still
* listening, let's better not try to use
* it. Note that we have no problem if the
* socket is completely down, since there
* might be a foreign /dev/log socket around
* and we want to make use of that.
*/
log_close_syslog();
return;
}
}
if ((u = manager_get_unit(m, SPECIAL_SYSLOG_TARGET)))
if (TARGET(u)->state != TARGET_ACTIVE) {
log_close_syslog();
return;
}
/* Hmm, OK, so the socket is either fully up, or fully down,
* and the target is up, then let's make use of the socket */
log_open();
}
static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {
[MANAGER_SYSTEM] = "system",
[MANAGER_USER] = "user"

View File

@ -211,6 +211,8 @@ struct Manager {
bool dispatching_run_queue:1;
bool dispatching_dbus_queue:1;
bool taint_usr:1;
bool show_status;
bool confirm_spawn;
#ifdef HAVE_SYSV_COMPAT
@ -285,6 +287,8 @@ void manager_check_finished(Manager *m);
void manager_run_generators(Manager *m);
void manager_undo_generators(Manager *m);
void manager_recheck_syslog(Manager *m);
const char *manager_running_as_to_string(ManagerRunningAs i);
ManagerRunningAs manager_running_as_from_string(const char *s);

View File

@ -36,6 +36,10 @@
#include "macro.h"
#ifdef ARCH_MIPS
#include <asm/sgidefs.h>
#endif
#ifndef RLIMIT_RTTIME
#define RLIMIT_RTTIME 15
#endif
@ -77,19 +81,42 @@ static inline int pivot_root(const char *new_root, const char *put_old) {
}
#ifdef __x86_64__
#ifndef __NR_fanotify_init
#define __NR_fanotify_init 300
#endif
#ifndef __NR_fanotify_mark
#define __NR_fanotify_mark 301
#endif
# ifndef __NR_fanotify_init
# define __NR_fanotify_init 300
# endif
# ifndef __NR_fanotify_mark
# define __NR_fanotify_mark 301
# endif
#elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# ifndef __NR_fanotify_init
# define __NR_fanotify_init 4336
# endif
# ifndef __NR_fanotify_mark
# define __NR_fanotify_mark 4337
# endif
# elif _MIPS_SIM == _MIPS_SIM_NABI32
# ifndef __NR_fanotify_init
# define __NR_fanotify_init 6300
# endif
# ifndef __NR_fanotify_mark
# define __NR_fanotify_mark 6301
# endif
# elif _MIPS_SIM == _MIPS_SIM_ABI64
# ifndef __NR_fanotify_init
# define __NR_fanotify_init 5295
# endif
# ifndef __NR_fanotify_mark
# define __NR_fanotify_mark 5296
# endif
# endif
#else
#ifndef __NR_fanotify_init
#define __NR_fanotify_init 338
#endif
#ifndef __NR_fanotify_mark
#define __NR_fanotify_mark 339
#endif
# ifndef __NR_fanotify_init
# define __NR_fanotify_init 338
# endif
# ifndef __NR_fanotify_mark
# define __NR_fanotify_mark 339
# endif
#endif
static inline int fanotify_init(unsigned int flags, unsigned int event_f_flags) {
@ -122,4 +149,8 @@ struct btrfs_ioctl_vol_args {
#define BTRFS_SUPER_MAGIC 0x9123683E
#endif
#ifndef MS_MOVE
#define MS_MOVE 8192
#endif
#endif

View File

@ -99,17 +99,21 @@ int main(int argc, char *argv[]) {
}
f = fopen(fn, "re");
free(fn);
if (!f) {
if (errno == ENOENT)
if (errno == ENOENT) {
free(fn);
continue;
}
log_error("Failed to open %s: %m", fn);
free(fn);
r = EXIT_FAILURE;
continue;
}
free(fn);
for (;;) {
char line[LINE_MAX], *l, *t;

View File

@ -54,6 +54,7 @@ static const MountPoint mount_table[] = {
{ "devtmpfs", "/dev", "devtmpfs", "mode=755", MS_NOSUID, true },
{ "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV, true },
{ "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, false },
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
{ "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
{ "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
};
@ -100,7 +101,7 @@ static int mount_one(const MountPoint *p) {
return r;
if (r > 0)
return 0;
goto finish;
/* The access mode here doesn't really matter too much, since
* the mounted file system will take precedence anyway. */
@ -121,6 +122,7 @@ static int mount_one(const MountPoint *p) {
return p->fatal ? -errno : 0;
}
finish:
label_fix(p->where, false);
return 0;
@ -227,8 +229,7 @@ int mount_setup(void) {
"/proc/self/fd\0" "/dev/fd\0"
"/proc/self/fd/0\0" "/dev/stdin\0"
"/proc/self/fd/1\0" "/dev/stdout\0"
"/proc/self/fd/2\0" "/dev/stderr\0"
"\0";
"/proc/self/fd/2\0" "/dev/stderr\0";
int r;
unsigned i;
@ -242,8 +243,10 @@ int mount_setup(void) {
* appropriate labels, after mounting. The other virtual API
* file systems do not need. */
if (unlink("/dev/.systemd/relabel-devtmpfs") >= 0)
if (unlink("/dev/.systemd-relabel-run-dev") >= 0) {
nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS);
nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS);
}
/* Create a few default symlinks, which are normally created
* bei udevd, but some scripts might need them before we start
@ -252,5 +255,9 @@ int mount_setup(void) {
NULSTR_FOREACH_PAIR(j, k, symlinks)
symlink_and_label(j, k);
/* Create a few directories we always want around */
mkdir("/run/systemd", 0755);
mkdir("/run/systemd/ask-password", 0755);
return mount_cgroup_controllers();
}

View File

@ -37,6 +37,7 @@
#include "special.h"
#include "bus-errors.h"
#include "exit-status.h"
#include "def.h"
static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
[MOUNT_DEAD] = UNIT_INACTIVE,
@ -127,6 +128,26 @@ static void mount_done(Unit *u) {
unit_unwatch_timer(u, &m->timer_watch);
}
static MountParameters* get_mount_parameters_configured(Mount *m) {
assert(m);
if (m->from_fragment)
return &m->parameters_fragment;
else if (m->from_etc_fstab)
return &m->parameters_etc_fstab;
return NULL;
}
static MountParameters* get_mount_parameters(Mount *m) {
assert(m);
if (m->from_proc_self_mountinfo)
return &m->parameters_proc_self_mountinfo;
return get_mount_parameters_configured(m);
}
static int mount_add_mount_links(Mount *m) {
Meta *other;
int r;
@ -134,12 +155,7 @@ static int mount_add_mount_links(Mount *m) {
assert(m);
if (m->from_fragment)
pm = &m->parameters_fragment;
else if (m->from_etc_fstab)
pm = &m->parameters_etc_fstab;
else
pm = NULL;
pm = get_mount_parameters_configured(m);
/* Adds in links to other mount points that might lie below or
* above us in the hierarchy */
@ -154,19 +170,14 @@ static int mount_add_mount_links(Mount *m) {
if (n->meta.load_state != UNIT_LOADED)
continue;
if (n->from_fragment)
pn = &n->parameters_fragment;
else if (n->from_etc_fstab)
pn = &n->parameters_etc_fstab;
else
pn = NULL;
pn = get_mount_parameters_configured(n);
if (path_startswith(m->where, n->where)) {
if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
return r;
if (n->from_etc_fstab || n->from_fragment)
if (pn)
if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
return r;
@ -175,7 +186,7 @@ static int mount_add_mount_links(Mount *m) {
if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
return r;
if (m->from_etc_fstab || m->from_fragment)
if (pm)
if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
return r;
@ -184,18 +195,16 @@ static int mount_add_mount_links(Mount *m) {
if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
return r;
if (m->from_etc_fstab || m->from_fragment)
if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
return r;
if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
return r;
} else if (pn && path_startswith(pn->what, m->where)) {
if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
return r;
if (n->from_etc_fstab || n->from_fragment)
if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
return r;
if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
return r;
}
}
@ -271,6 +280,43 @@ static char* mount_test_option(const char *haystack, const char *needle) {
return hasmntopt(&me, needle);
}
static bool mount_is_network(MountParameters *p) {
assert(p);
if (mount_test_option(p->options, "_netdev"))
return true;
if (p->fstype && fstype_is_network(p->fstype))
return true;
return false;
}
static bool mount_is_bind(MountParameters *p) {
assert(p);
if (mount_test_option(p->options, "bind"))
return true;
if (p->fstype && streq(p->fstype, "bind"))
return true;
return false;
}
static bool needs_quota(MountParameters *p) {
assert(p);
if (mount_is_network(p))
return false;
if (mount_is_bind(p))
return false;
return mount_test_option(p->options, "usrquota") ||
mount_test_option(p->options, "grpquota");
}
static int mount_add_target_links(Mount *m) {
const char *target, *after = NULL;
MountParameters *p;
@ -280,11 +326,7 @@ static int mount_add_target_links(Mount *m) {
assert(m);
if (m->from_fragment)
p = &m->parameters_fragment;
else if (m->from_etc_fstab)
p = &m->parameters_etc_fstab;
else
if (!(p = get_mount_parameters_configured(m)))
return 0;
noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
@ -297,8 +339,7 @@ static int mount_add_target_links(Mount *m) {
mount_test_option(p->options, "comment=systemd.automount") ||
mount_test_option(p->options, "x-systemd-automount");
if (mount_test_option(p->options, "_netdev") ||
(p->fstype && fstype_is_network(p->fstype))) {
if (mount_is_network(p)) {
target = SPECIAL_REMOTE_FS_TARGET;
if (m->meta.manager->running_as == MANAGER_SYSTEM)
@ -336,29 +377,13 @@ static int mount_add_target_links(Mount *m) {
}
}
static bool mount_is_bind(MountParameters *p) {
assert(p);
if (p->fstype && streq(p->fstype, "bind"))
return true;
if (mount_test_option(p->options, "bind"))
return true;
return false;
}
static int mount_add_device_links(Mount *m) {
MountParameters *p;
int r;
assert(m);
if (m->from_fragment)
p = &m->parameters_fragment;
else if (m->from_etc_fstab)
p = &m->parameters_etc_fstab;
else
if (!(p = get_mount_parameters_configured(m)))
return 0;
if (!p->what)
@ -412,9 +437,15 @@ static int mount_add_default_dependencies(Mount *m) {
if (m->meta.manager->running_as == MANAGER_SYSTEM &&
!path_equal(m->where, "/")) {
MountParameters *p;
if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, SPECIAL_QUOTACHECK_SERVICE, NULL, true)) < 0)
return r;
p = get_mount_parameters_configured(m);
if (p && needs_quota(p)) {
if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true)) < 0 ||
(r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true)) < 0)
return r;
}
if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
return r;
@ -445,6 +476,11 @@ static int mount_verify(Mount *m) {
return -EINVAL;
}
if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
log_error("Cannot create mount unit for API file system %s. Refusing.", m->where);
return -EINVAL;
}
if (m->meta.fragment_path && !m->parameters_fragment.what) {
log_error("%s's What setting is missing. Refusing.", m->meta.id);
return -EBADMSG;
@ -626,12 +662,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
assert(m);
assert(f);
if (m->from_proc_self_mountinfo)
p = &m->parameters_proc_self_mountinfo;
else if (m->from_fragment)
p = &m->parameters_fragment;
else
p = &m->parameters_etc_fstab;
p = get_mount_parameters(m);
fprintf(f,
"%sMount State: %s\n"
@ -733,9 +764,7 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) {
state == MOUNT_REMOUNTING_SIGTERM) ? m->exec_context.kill_signal : SIGKILL;
if (m->control_pid > 0) {
if (kill_and_sigcont(m->exec_context.kill_mode == KILL_PROCESS_GROUP ?
-m->control_pid :
m->control_pid, sig) < 0 && errno != ESRCH)
if (kill_and_sigcont(m->control_pid, sig) < 0 && errno != ESRCH)
log_warning("Failed to kill control process %li: %m", (long) m->control_pid);
else
@ -761,6 +790,7 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) {
wait_for_exit = true;
set_free(pid_set);
pid_set = NULL;
}
}
@ -822,6 +852,7 @@ fail:
static void mount_enter_mounting(Mount *m) {
int r;
MountParameters *p;
assert(m);
@ -830,6 +861,11 @@ static void mount_enter_mounting(Mount *m) {
mkdir_p(m->where, m->directory_mode);
/* Create the source directory for bind-mounts if needed */
p = get_mount_parameters_configured(m);
if (p && mount_is_bind(p))
mkdir_p(p->what, m->directory_mode);
if (m->from_fragment)
r = exec_command_set(
m->control_command,
@ -1269,9 +1305,7 @@ static int mount_add_one(
/* Ignore API mount points. They should never be referenced in
* dependencies ever. */
if (mount_point_is_api(where))
return 0;
if (mount_point_ignore(where))
if (mount_point_is_api(where) || mount_point_ignore(where))
return 0;
if (streq(fstype, "autofs"))
@ -1666,7 +1700,7 @@ static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
}
if (m->control_pid > 0)
if (kill(mode == KILL_PROCESS_GROUP ? -m->control_pid : m->control_pid, signo) < 0)
if (kill(m->control_pid, signo) < 0)
r = -errno;
if (mode == KILL_CONTROL_GROUP) {

800
src/nspawn.c Normal file
View File

@ -0,0 +1,800 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <signal.h>
#include <sched.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/prctl.h>
#include <sys/capability.h>
#include <getopt.h>
#include <sys/epoll.h>
#include <termios.h>
#include <sys/signalfd.h>
#include "log.h"
#include "util.h"
#include "missing.h"
#include "cgroup-util.h"
#include "sd-daemon.h"
#include "strv.h"
static char *arg_directory = NULL;
static int help(void) {
printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
"Spawn a minimal namespace container for debugging, testing and building.\n\n"
" -h --help Show this help\n"
" -D --directory=NAME Root directory for the container\n",
program_invocation_short_name);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "directory", required_argument, NULL, 'D' },
{ NULL, 0, NULL, 0 }
};
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "+hD:", options, NULL)) >= 0) {
switch (c) {
case 'h':
help();
return 0;
case 'D':
free(arg_directory);
if (!(arg_directory = strdup(optarg))) {
log_error("Failed to duplicate root directory.");
return -ENOMEM;
}
break;
case '?':
return -EINVAL;
default:
log_error("Unknown option code %c", c);
return -EINVAL;
}
}
return 1;
}
static int mount_all(const char *dest) {
typedef struct MountPoint {
const char *what;
const char *where;
const char *type;
const char *options;
unsigned long flags;
bool fatal;
} MountPoint;
static const MountPoint mount_table[] = {
{ "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
{ "/proc/sys", "/proc/sys", "bind", NULL, MS_BIND, true }, /* Bind mount first */
{ "/proc/sys", "/proc/sys", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
{ "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, true },
{ "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID, true },
{ "/dev/pts", "/dev/pts", "bind", NULL, MS_BIND, true },
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
#ifdef HAVE_SELINUX
{ "selinux", "/selinux", "selinuxfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, false },
#endif
};
unsigned k;
int r = 0;
char *where;
for (k = 0; k < ELEMENTSOF(mount_table); k++) {
int t;
if (asprintf(&where, "%s/%s", dest, mount_table[k].where) < 0) {
log_error("Out of memory");
if (r == 0)
r = -ENOMEM;
break;
}
if ((t = path_is_mount_point(where)) < 0) {
log_error("Failed to detect whether %s is a mount point: %s", where, strerror(-t));
free(where);
if (r == 0)
r = t;
continue;
}
mkdir_p(where, 0755);
if (mount(mount_table[k].what,
where,
mount_table[k].type,
mount_table[k].flags,
mount_table[k].options) < 0 &&
mount_table[k].fatal) {
log_error("mount(%s) failed: %m", where);
if (r == 0)
r = -errno;
}
free(where);
}
/* Fix the timezone, if possible */
if (asprintf(&where, "%s/%s", dest, "/etc/localtime") >= 0) {
mount("/etc/localtime", where, "bind", MS_BIND, NULL);
mount("/etc/localtime", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
free(where);
}
return r;
}
static int copy_devnodes(const char *dest, const char *console) {
static const char devnodes[] =
"null\0"
"zero\0"
"full\0"
"random\0"
"urandom\0"
"tty\0"
"ptmx\0"
"kmsg\0"
"rtc0\0";
const char *d;
int r = 0, k;
mode_t u;
struct stat st;
char *from = NULL, *to = NULL;
assert(dest);
assert(console);
u = umask(0000);
NULSTR_FOREACH(d, devnodes) {
from = to = NULL;
asprintf(&from, "/dev/%s", d);
asprintf(&to, "%s/dev/%s", dest, d);
if (!from || !to) {
log_error("Failed to allocate devnode path");
free(from);
free(to);
from = to = NULL;
if (r == 0)
r = -ENOMEM;
break;
}
if (stat(from, &st) < 0) {
if (errno != ENOENT) {
log_error("Failed to stat %s: %m", from);
if (r == 0)
r = -errno;
}
} else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
log_error("%s is not a char or block device, cannot copy.", from);
if (r == 0)
r = -EIO;
} else if (mknod(to, st.st_mode, st.st_rdev) < 0) {
log_error("mknod(%s) failed: %m", dest);
if (r == 0)
r = -errno;
}
free(from);
free(to);
}
if (stat(console, &st) < 0) {
log_error("Failed to stat %s: %m", console);
if (r == 0)
r = -errno;
goto finish;
} else if (!S_ISCHR(st.st_mode)) {
log_error("/dev/console is not a char device.");
if (r == 0)
r = -EIO;
goto finish;
}
if (asprintf(&to, "%s/dev/console", dest) < 0) {
log_error("Out of memory");
if (r == 0)
r = -ENOMEM;
goto finish;
}
/* We need to bind mount the right tty to /dev/console since
* ptys can only exist on pts file systems. To have something
* to bind mount things on we create a device node first, that
* has the right major/minor (note that the major minor
* doesn't actually matter here, since we mount it over
* anyway). */
if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0)
log_error("mknod for /dev/console failed: %m");
if (mount(console, to, "bind", MS_BIND, NULL) < 0) {
log_error("bind mount for /dev/console failed: %m");
if (r == 0)
r = -errno;
}
free(to);
if ((k = chmod_and_chown(console, 0600, 0, 0)) < 0) {
log_error("Failed to correct access mode for TTY: %s", strerror(-k));
if (r == 0)
r = k;
}
finish:
umask(u);
return r;
}
static int drop_capabilities(void) {
static const unsigned long retain[] = {
CAP_CHOWN,
CAP_DAC_OVERRIDE,
CAP_DAC_READ_SEARCH,
CAP_FOWNER,
CAP_FSETID,
CAP_IPC_OWNER,
CAP_KILL,
CAP_LEASE,
CAP_LINUX_IMMUTABLE,
CAP_NET_BIND_SERVICE,
CAP_NET_BROADCAST,
CAP_NET_RAW,
CAP_SETGID,
CAP_SETFCAP,
CAP_SETPCAP,
CAP_SETUID,
CAP_SYS_ADMIN,
CAP_SYS_CHROOT,
CAP_SYS_NICE,
CAP_SYS_PTRACE,
CAP_SYS_TTY_CONFIG
};
unsigned long l;
for (l = 0; l <= MAX(63LU, (unsigned long) CAP_LAST_CAP); l ++) {
unsigned i;
for (i = 0; i < ELEMENTSOF(retain); i++)
if (retain[i] == l)
break;
if (i < ELEMENTSOF(retain))
continue;
if (prctl(PR_CAPBSET_DROP, l) < 0) {
/* If this capability is not known, EINVAL
* will be returned, let's ignore this. */
if (errno == EINVAL)
continue;
log_error("PR_CAPBSET_DROP failed: %m");
return -errno;
}
}
return 0;
}
static int is_os_tree(const char *path) {
int r;
char *p;
/* We use /bin/sh as flag file if something is an OS */
if (asprintf(&p, "%s/bin/sh", path) < 0)
return -ENOMEM;
r = access(p, F_OK);
free(p);
return r < 0 ? 0 : 1;
}
#define BUFFER_SIZE 1024
static int process_pty(int master, sigset_t *mask) {
char in_buffer[BUFFER_SIZE], out_buffer[BUFFER_SIZE];
size_t in_buffer_full = 0, out_buffer_full = 0;
struct epoll_event stdin_ev, stdout_ev, master_ev, signal_ev;
bool stdin_readable = false, stdout_writable = false, master_readable = false, master_writable = false;
int ep = -1, signal_fd = -1, r;
fd_nonblock(STDIN_FILENO, 1);
fd_nonblock(STDOUT_FILENO, 1);
fd_nonblock(master, 1);
if ((signal_fd = signalfd(-1, mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
log_error("signalfd(): %m");
r = -errno;
goto finish;
}
if ((ep = epoll_create1(EPOLL_CLOEXEC)) < 0) {
log_error("Failed to create epoll: %m");
r = -errno;
goto finish;
}
zero(stdin_ev);
stdin_ev.events = EPOLLIN|EPOLLET;
stdin_ev.data.fd = STDIN_FILENO;
zero(stdout_ev);
stdout_ev.events = EPOLLOUT|EPOLLET;
stdout_ev.data.fd = STDOUT_FILENO;
zero(master_ev);
master_ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
master_ev.data.fd = master;
zero(signal_ev);
signal_ev.events = EPOLLIN;
signal_ev.data.fd = signal_fd;
if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev) < 0 ||
epoll_ctl(ep, EPOLL_CTL_ADD, STDOUT_FILENO, &stdout_ev) < 0 ||
epoll_ctl(ep, EPOLL_CTL_ADD, master, &master_ev) < 0 ||
epoll_ctl(ep, EPOLL_CTL_ADD, signal_fd, &signal_ev) < 0) {
log_error("Failed to regiser fds in epoll: %m");
r = -errno;
goto finish;
}
for (;;) {
struct epoll_event ev[16];
ssize_t k;
int i, nfds;
if ((nfds = epoll_wait(ep, ev, ELEMENTSOF(ev), -1)) < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
log_error("epoll_wait(): %m");
r = -errno;
goto finish;
}
assert(nfds >= 1);
for (i = 0; i < nfds; i++) {
if (ev[i].data.fd == STDIN_FILENO) {
if (ev[i].events & (EPOLLIN|EPOLLHUP))
stdin_readable = true;
} else if (ev[i].data.fd == STDOUT_FILENO) {
if (ev[i].events & (EPOLLOUT|EPOLLHUP))
stdout_writable = true;
} else if (ev[i].data.fd == master) {
if (ev[i].events & (EPOLLIN|EPOLLHUP))
master_readable = true;
if (ev[i].events & (EPOLLOUT|EPOLLHUP))
master_writable = true;
} else if (ev[i].data.fd == signal_fd) {
struct signalfd_siginfo sfsi;
ssize_t n;
if ((n = read(signal_fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
if (n >= 0) {
r = -EIO;
goto finish;
}
if (errno != EINTR && errno != EAGAIN) {
r = -errno;
goto finish;
}
} else {
if (sfsi.ssi_signo == SIGWINCH) {
struct winsize ws;
/* The window size changed, let's forward that. */
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
ioctl(master, TIOCSWINSZ, &ws);
} else {
r = -EINTR;
goto finish;
}
}
}
}
while ((stdin_readable && in_buffer_full <= 0) ||
(master_writable && in_buffer_full > 0) ||
(master_readable && out_buffer_full <= 0) ||
(stdout_writable && out_buffer_full > 0)) {
if (stdin_readable && in_buffer_full < BUFFER_SIZE) {
if ((k = read(STDIN_FILENO, in_buffer + in_buffer_full, BUFFER_SIZE - in_buffer_full)) < 0) {
if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
stdin_readable = false;
else {
log_error("read(): %m");
goto finish;
}
} else
in_buffer_full += (size_t) k;
}
if (master_writable && in_buffer_full > 0) {
if ((k = write(master, in_buffer, in_buffer_full)) < 0) {
if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
master_writable = false;
else {
log_error("write(): %m");
goto finish;
}
} else {
assert(in_buffer_full >= (size_t) k);
memmove(in_buffer, in_buffer + k, in_buffer_full - k);
in_buffer_full -= k;
}
}
if (master_readable && out_buffer_full < BUFFER_SIZE) {
if ((k = read(master, out_buffer + out_buffer_full, BUFFER_SIZE - out_buffer_full)) < 0) {
if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
master_readable = false;
else {
log_error("read(): %m");
goto finish;
}
} else
out_buffer_full += (size_t) k;
}
if (stdout_writable && out_buffer_full > 0) {
if ((k = write(STDOUT_FILENO, out_buffer, out_buffer_full)) < 0) {
if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
stdout_writable = false;
else {
log_error("write(): %m");
goto finish;
}
} else {
assert(out_buffer_full >= (size_t) k);
memmove(out_buffer, out_buffer + k, out_buffer_full - k);
out_buffer_full -= k;
}
}
}
}
finish:
if (ep >= 0)
close_nointr_nofail(ep);
if (signal_fd >= 0)
close_nointr_nofail(signal_fd);
return r;
}
int main(int argc, char *argv[]) {
pid_t pid = 0;
int r = EXIT_FAILURE, k;
char *oldcg = NULL, *newcg = NULL;
int master = -1;
const char *console = NULL;
struct termios saved_attr, raw_attr;
sigset_t mask;
bool saved_attr_valid = false;
struct winsize ws;
log_parse_environment();
log_open();
if ((r = parse_argv(argc, argv)) <= 0)
goto finish;
if (arg_directory) {
char *p;
p = path_make_absolute_cwd(arg_directory);
free(arg_directory);
arg_directory = p;
} else
arg_directory = get_current_dir_name();
if (!arg_directory) {
log_error("Failed to determine path");
goto finish;
}
path_kill_slashes(arg_directory);
if (geteuid() != 0) {
log_error("Need to be root.");
goto finish;
}
if (sd_booted() <= 0) {
log_error("Not running on a systemd system.");
goto finish;
}
if (path_equal(arg_directory, "/")) {
log_error("Spawning container on root directory not supported.");
goto finish;
}
if (is_os_tree(arg_directory) <= 0) {
log_error("Directory %s doesn't look like an OS root directory. Refusing.", arg_directory);
goto finish;
}
if ((k = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &oldcg)) < 0) {
log_error("Failed to determine current cgroup: %s", strerror(-k));
goto finish;
}
if (asprintf(&newcg, "%s/nspawn-%lu", oldcg, (unsigned long) getpid()) < 0) {
log_error("Failed to allocate cgroup path.");
goto finish;
}
if ((k = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, newcg, 0)) < 0) {
log_error("Failed to create cgroup: %s", strerror(-k));
goto finish;
}
if ((master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY)) < 0) {
log_error("Failed to acquire pseudo tty: %m");
goto finish;
}
if (!(console = ptsname(master))) {
log_error("Failed to determine tty name: %m");
goto finish;
}
log_info("Spawning namespace container on %s (console is %s).", arg_directory, console);
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
ioctl(master, TIOCSWINSZ, &ws);
if (unlockpt(master) < 0) {
log_error("Failed to unlock tty: %m");
goto finish;
}
if (tcgetattr(STDIN_FILENO, &saved_attr) < 0) {
log_error("Failed to get terminal attributes: %m");
goto finish;
}
saved_attr_valid = true;
raw_attr = saved_attr;
cfmakeraw(&raw_attr);
raw_attr.c_lflag &= ~ECHO;
if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr) < 0) {
log_error("Failed to set terminal attributes: %m");
goto finish;
}
assert_se(sigemptyset(&mask) == 0);
sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
if ((pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS, NULL)) < 0) {
log_error("clone() failed: %m");
goto finish;
}
if (pid == 0) {
/* child */
const char *hn;
const char *envp[] = {
"HOME=/root",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
NULL,
NULL
};
envp[2] = strv_find_prefix(environ, "TERM=");
close_nointr_nofail(master);
close_nointr(STDIN_FILENO);
close_nointr(STDOUT_FILENO);
close_nointr(STDERR_FILENO);
close_all_fds(NULL, 0);
reset_all_signal_handlers();
assert_se(sigemptyset(&mask) == 0);
assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
if (setsid() < 0)
goto child_fail;
if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
goto child_fail;
if (mount_all(arg_directory) < 0)
goto child_fail;
if (copy_devnodes(arg_directory, console) < 0)
goto child_fail;
if (chdir(arg_directory) < 0) {
log_error("chdir(%s) failed: %m", arg_directory);
goto child_fail;
}
if (open_terminal("dev/console", O_RDWR) != STDIN_FILENO ||
dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
goto child_fail;
if (mount(arg_directory, "/", "bind", MS_BIND|MS_MOVE, NULL) < 0) {
log_error("mount(MS_MOVE) failed: %m");
goto child_fail;
}
if (chroot(".") < 0) {
log_error("chroot() failed: %m");
goto child_fail;
}
if (chdir("/") < 0) {
log_error("chdir() failed: %m");
goto child_fail;
}
umask(0002);
if (drop_capabilities() < 0)
goto child_fail;
if ((hn = file_name_from_path(arg_directory)))
sethostname(hn, strlen(hn));
if (argc > optind)
execvpe(argv[optind], argv + optind, (char**) envp);
else {
chdir("/root");
execle("/bin/bash", "-bash", NULL, (char**) envp);
}
log_error("execv() failed: %m");
child_fail:
_exit(EXIT_FAILURE);
}
if (process_pty(master, &mask) < 0)
goto finish;
if (saved_attr_valid) {
tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
saved_attr_valid = false;
}
r = wait_for_terminate_and_warn(argc > optind ? argv[optind] : "bash", pid);
if (r < 0)
r = EXIT_FAILURE;
finish:
if (saved_attr_valid)
tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
if (master >= 0)
close_nointr_nofail(master);
if (oldcg)
cg_attach(SYSTEMD_CGROUP_CONTROLLER, oldcg, 0);
if (newcg)
cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
free(arg_directory);
free(oldcg);
free(newcg);
return r;
}

View File

@ -50,6 +50,10 @@
send_interface="org.freedesktop.systemd1.Manager"
send_member="GetUnitByPID"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="LoadUnit"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="GetJob"/>

View File

@ -24,7 +24,18 @@
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/lib/systemd/systemd-reply-password</annotate>
<annotate key="org.freedesktop.policykit.exec.path">@rootlibexecdir@/systemd-reply-password</annotate>
</action>
<action id="org.freedesktop.systemd1.BusAccess">
<description>Privileged system and service manager access</description>
<message>Authentication is required to access the system and service manager.</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">@bindir@/systemd-stdio-bridge</annotate>
</action>
</policyconfig>

View File

@ -198,8 +198,10 @@ static int open_file_and_lock(const char *fn) {
* as the filesystems in question should be local, and only
* locally accessible, and most likely even tmpfs. */
if (flock(fd, LOCK_EX) < 0)
if (flock(fd, LOCK_EX) < 0) {
close_nointr_nofail(fd);
return -errno;
}
return fd;
}
@ -237,11 +239,10 @@ static uint64_t get_session_id(int *mode) {
ssize_t r;
/* We do a bit of endianess swapping here, just to be
* sure. /var should be machine specific anyway, and
* /var/run even mounted from tmpfs, so this
* byteswapping should really not be necessary. But
* then again, you never know, so let's avoid any
* risk. */
* sure. /run should be machine specific anyway, and
* even mounted from tmpfs, so this byteswapping
* should really not be necessary. But then again, you
* never know, so let's avoid any risk. */
if (loop_read(fd, &counter, sizeof(counter), false) != sizeof(counter))
counter = 1;
@ -271,6 +272,7 @@ static uint64_t get_session_id(int *mode) {
/* Last attempt, pick a random value */
return (uint64_t) random_ull();
}
static int get_user_data(
pam_handle_t *handle,
const char **ret_username,
@ -394,6 +396,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
int lock_fd = -1;
bool create_session = true;
char **controllers = NULL, **reset_controllers = NULL, **c;
char *cgroup_user_tree = NULL;
assert(handle);
@ -413,6 +416,12 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if ((r = get_user_data(handle, &username, &pw)) != PAM_SUCCESS)
goto finish;
if ((r = cg_get_user_path(&cgroup_user_tree)) < 0) {
pam_syslog(handle, LOG_ERR, "Failed to determine user cgroup tree: %s", strerror(-r));
r = PAM_SYSTEM_ERR;
goto finish;
}
if (safe_mkdir(RUNTIME_DIR "/user", 0755, 0, 0) < 0) {
pam_syslog(handle, LOG_ERR, "Failed to create runtime directory: %m");
r = PAM_SYSTEM_ERR;
@ -425,7 +434,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
goto finish;
}
/* Create /var/run/$USER */
/* Create /run/user/$USER */
free(buf);
if (asprintf(&buf, RUNTIME_DIR "/user/%s", username) < 0) {
r = PAM_BUF_ERR;
@ -476,9 +485,9 @@ _public_ PAM_EXTERN int pam_sm_open_session(
}
}
r = asprintf(&buf, "/user/%s/%s", username, id);
r = asprintf(&buf, "%s/%s/%s", cgroup_user_tree, username, id);
} else
r = asprintf(&buf, "/user/%s/master", username);
r = asprintf(&buf, "%s/%s/master", cgroup_user_tree, username);
if (r < 0) {
r = PAM_BUF_ERR;
@ -509,6 +518,8 @@ finish:
strv_free(controllers);
strv_free(reset_controllers);
free(cgroup_user_tree);
return r;
}
@ -600,6 +611,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
struct passwd *pw;
const void *created = NULL;
char **controllers = NULL, **c, **kill_only_users = NULL, **kill_exclude_users = NULL;
char *cgroup_user_tree = NULL;
assert(handle);
@ -617,6 +629,12 @@ _public_ PAM_EXTERN int pam_sm_close_session(
if ((r = get_user_data(handle, &username, &pw)) != PAM_SUCCESS)
goto finish;
if ((r = cg_get_user_path(&cgroup_user_tree)) < 0) {
pam_syslog(handle, LOG_ERR, "Failed to determine user cgroup tree: %s", strerror(-r));
r = PAM_SYSTEM_ERR;
goto finish;
}
if ((lock_fd = open_file_and_lock(RUNTIME_DIR "/user/.pam-systemd-lock")) < 0) {
pam_syslog(handle, LOG_ERR, "Failed to lock runtime directory: %m");
r = PAM_SYSTEM_ERR;
@ -624,14 +642,14 @@ _public_ PAM_EXTERN int pam_sm_close_session(
}
/* We are probably still in some session/user dir. Move ourselves out of the way as first step */
if ((r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/user", 0)) < 0)
if ((r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, cgroup_user_tree, 0)) < 0)
pam_syslog(handle, LOG_ERR, "Failed to move us away: %s", strerror(-r));
STRV_FOREACH(c, controllers)
if ((r = cg_attach(*c, "/user", 0)) < 0)
if ((r = cg_attach(*c, cgroup_user_tree, 0)) < 0)
pam_syslog(handle, LOG_ERR, "Failed to move us away in %s hierarchy: %s", *c, strerror(-r));
if (asprintf(&user_path, "/user/%s", username) < 0) {
if (asprintf(&user_path, "%s/%s", cgroup_user_tree, username) < 0) {
r = PAM_BUF_ERR;
goto finish;
}
@ -640,8 +658,8 @@ _public_ PAM_EXTERN int pam_sm_close_session(
if ((id = pam_getenv(handle, "XDG_SESSION_ID")) && created) {
if (asprintf(&session_path, "/user/%s/%s", username, id) < 0 ||
asprintf(&nosession_path, "/user/%s/master", username) < 0) {
if (asprintf(&session_path, "%s/%s/%s", cgroup_user_tree, username, id) < 0 ||
asprintf(&nosession_path, "%s/%s/master", cgroup_user_tree, username) < 0) {
r = PAM_BUF_ERR;
goto finish;
}
@ -727,5 +745,7 @@ finish:
strv_free(kill_exclude_users);
strv_free(kill_only_users);
free(cgroup_user_tree);
return r;
}

View File

@ -102,7 +102,11 @@ static char** user_dirs(void) {
if ((e = getenv("XDG_DATA_DIRS")))
data_dirs = strv_split(e, ":");
else
data_dirs = strv_new("/usr/local/share", "/usr/share", NULL);
data_dirs = strv_new("/usr/local/share",
"/usr/local/lib",
"/usr/share",
"/usr/lib",
NULL);
if (!data_dirs)
goto fail;
@ -181,11 +185,15 @@ int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as) {
return -ENOMEM;
} else
if (!(p->unit_path = strv_new(
"/dev/.systemd/system",
/* If you modify this you also want to modify
* systemdsystemunitpath= in systemd.pc.in! */
"/run/systemd/system",
SYSTEM_CONFIG_UNIT_PATH,
"/etc/systemd/system",
"/usr/local/share/systemd/system",
"/usr/local/lib/systemd/system",
"/usr/share/systemd/system",
"/usr/lib/systemd/system",
"/lib/systemd/system",
SYSTEM_DATA_UNIT_PATH,
NULL)))

View File

@ -35,6 +35,9 @@ static int parse_proc_cmdline(void) {
int r;
size_t l;
if (detect_container(NULL) > 0)
return 0;
if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
return 0;
@ -94,7 +97,7 @@ int main(int argc, char *argv[]) {
if (arg_skip)
return 0;
if (access("/dev/.systemd/quotacheck", F_OK) < 0)
if (access("/run/systemd/quotacheck", F_OK) < 0)
return 0;
}
@ -107,7 +110,7 @@ int main(int argc, char *argv[]) {
_exit(1); /* Operational error */
}
r = wait_for_terminate_and_warn("quotacheck", pid) >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
r = wait_for_terminate_and_warn("quotacheck", pid) == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
finish:
return r;

View File

@ -86,9 +86,11 @@ int main(int argc, char *argv[]) {
}
}
if ((r = loop_read(seed_fd, buf, buf_size, false)) <= 0)
log_error("Failed to read seed file: %s", r < 0 ? strerror(errno) : "EOF");
else {
if ((r = loop_read(seed_fd, buf, buf_size, false)) <= 0) {
if (r != 0)
log_error("Failed to read seed file: %m");
} else {
lseek(seed_fd, 0, SEEK_SET);
if ((r = loop_write(random_fd, buf, (size_t) r, false)) <= 0)

View File

@ -119,9 +119,10 @@ static int pack_file(FILE *pack, const char *fn, bool on_btrfs) {
goto finish;
}
pages = l / PAGE_SIZE;
pages = l / page_size();
vec = alloca(pages);
memset(vec, 0, pages);
if (mincore(start, l, vec) < 0) {
log_warning("mincore(%s) failed: %m", fn);
r = -errno;
@ -289,13 +290,13 @@ static int collect(const char *root) {
log_debug("Collecting...");
if (access("/dev/.systemd/readahead/cancel", F_OK) >= 0) {
if (access("/run/systemd/readahead/cancel", F_OK) >= 0) {
log_debug("Collection canceled");
r = -ECANCELED;
goto finish;
}
if (access("/dev/.systemd/readahead/done", F_OK) >= 0) {
if (access("/run/systemd/readahead/done", F_OK) >= 0) {
log_debug("Got termination request");
goto done;
}

View File

@ -167,11 +167,11 @@ int open_inotify(void) {
return -errno;
}
mkdir("/dev/.systemd", 0755);
mkdir("/dev/.systemd/readahead", 0755);
mkdir("/run/systemd", 0755);
mkdir("/run/systemd/readahead", 0755);
if (inotify_add_watch(fd, "/dev/.systemd/readahead", IN_CREATE) < 0) {
log_error("Failed to watch /dev/.systemd/readahead: %m");
if (inotify_add_watch(fd, "/run/systemd/readahead", IN_CREATE) < 0) {
log_error("Failed to watch /run/systemd/readahead: %m");
close_nointr_nofail(fd);
return -errno;
}
@ -183,10 +183,10 @@ ReadaheadShared *shared_get(void) {
int fd;
ReadaheadShared *m = NULL;
mkdir("/dev/.systemd", 0755);
mkdir("/dev/.systemd/readahead", 0755);
mkdir("/run/systemd", 0755);
mkdir("/run/systemd/readahead", 0755);
if ((fd = open("/dev/.systemd/readahead/shared", O_CREAT|O_RDWR|O_CLOEXEC, 0644)) < 0) {
if ((fd = open("/run/systemd/readahead/shared", O_CREAT|O_RDWR|O_CLOEXEC, 0644)) < 0) {
log_error("Failed to create shared memory segment: %m");
goto finish;
}

View File

@ -94,7 +94,7 @@ static int unpack_file(FILE *pack) {
any = true;
if (fd >= 0)
if (posix_fadvise(fd, b * PAGE_SIZE, (c - b) * PAGE_SIZE, POSIX_FADV_WILLNEED) < 0) {
if (posix_fadvise(fd, b * page_size(), (c - b) * page_size(), POSIX_FADV_WILLNEED) < 0) {
log_warning("posix_fadvise() failed: %m");
goto finish;
}
@ -122,7 +122,8 @@ static int replay(const char *root) {
FILE *pack = NULL;
char line[LINE_MAX];
int r = 0;
char *pack_fn = NULL, c;
char *pack_fn = NULL;
int c;
bool on_ssd, ready = false;
int prio;
int inotify_fd = -1;
@ -192,7 +193,7 @@ static int replay(const char *root) {
log_debug("Replaying...");
if (access("/dev/.systemd/readahead/noreplay", F_OK) >= 0) {
if (access("/run/systemd/readahead/noreplay", F_OK) >= 0) {
log_debug("Got termination request");
goto done;
}

View File

@ -42,8 +42,8 @@ static int touch(const char *path) {
#if !defined(DISABLE_SYSTEMD) && defined(__linux__)
int fd;
mkdir("/dev/.systemd", 0755);
mkdir("/dev/.systemd/readahead", 0755);
mkdir("/run/systemd", 0755);
mkdir("/run/systemd/readahead", 0755);
if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0666)) < 0)
return -errno;
@ -66,11 +66,11 @@ int sd_readahead(const char *action) {
return -EINVAL;
if (strcmp(action, "cancel") == 0)
return touch("/dev/.systemd/readahead/cancel");
return touch("/run/systemd/readahead/cancel");
else if (strcmp(action, "done") == 0)
return touch("/dev/.systemd/readahead/done");
return touch("/run/systemd/readahead/done");
else if (strcmp(action, "noreplay") == 0)
return touch("/dev/.systemd/readahead/noreplay");
return touch("/run/systemd/readahead/noreplay");
return -EINVAL;
}

View File

@ -43,10 +43,9 @@ int selinux_setup(char *const argv[]) {
return 0;
/* Before we load the policy we create a flag file to ensure
* that after the reexec we iterate through /dev to relabel
* things. */
mkdir_p("/dev/.systemd", 0755);
touch("/dev/.systemd/relabel-devtmpfs");
* that after the reexec we iterate through /run and /dev to
* relabel things. */
touch("/dev/.systemd-relabel-run-dev");
if (selinux_init_load_policy(&enforce) == 0) {
log_debug("Successfully loaded SELinux policy, reexecuting.");
@ -59,9 +58,9 @@ int selinux_setup(char *const argv[]) {
return -errno;
} else {
log_full(enforce > 0 ? LOG_ERR : LOG_DEBUG, "Failed to load SELinux policy.");
log_full(enforce > 0 ? LOG_ERR : LOG_WARNING, "Failed to load SELinux policy.");
unlink("/dev/.systemd/relabel-devtmpfs");
unlink("/dev/.systemd-relabel-run-dev");
if (enforce > 0)
return -EIO;

View File

@ -35,13 +35,12 @@
#include "special.h"
#include "bus-errors.h"
#include "exit-status.h"
#define COMMENTS "#;\n"
#define NEWLINES "\n\r"
#include "def.h"
#include "util.h"
#ifdef HAVE_SYSV_COMPAT
#define DEFAULT_SYSV_TIMEOUT_USEC (3*USEC_PER_MINUTE)
#define DEFAULT_SYSV_TIMEOUT_USEC (5*USEC_PER_MINUTE)
typedef enum RunlevelType {
RUNLEVEL_UP,
@ -116,6 +115,7 @@ static void service_init(Unit *u) {
s->timer_watch.type = WATCH_INVALID;
#ifdef HAVE_SYSV_COMPAT
s->sysv_start_priority = -1;
s->sysv_start_priority_from_rcnd = -1;
#endif
s->socket_fd = -1;
s->guess_main_pid = true;
@ -286,7 +286,7 @@ static int sysv_translate_facility(const char *name, const char *filename, char
"portmap", SPECIAL_RPCBIND_TARGET,
"remote_fs", SPECIAL_REMOTE_FS_TARGET,
"syslog", SPECIAL_SYSLOG_TARGET,
"time", SPECIAL_RTC_SET_TARGET,
"time", SPECIAL_TIME_SYNC_TARGET,
/* common extensions */
"mail-transfer-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
@ -406,7 +406,7 @@ static int sysv_fix_order(Service *s) {
/* FIXME: Maybe we should compare the name here lexicographically? */
if (!(r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
if ((r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
return r;
}
@ -538,7 +538,7 @@ static int service_load_sysv_path(Service *s, const char *path) {
* data from the LSB header. */
if (start_priority < 0 || start_priority > 99)
log_warning("[%s:%u] Start priority out of range. Ignoring.", path, line);
else if (s->sysv_start_priority < 0)
else
s->sysv_start_priority = start_priority;
char_array_0(runlevels);
@ -656,16 +656,21 @@ static int service_load_sysv_path(Service *s, const char *path) {
if (unit_name_to_type(m) == UNIT_SERVICE)
r = unit_add_name(u, m);
else {
r = unit_add_dependency_by_name(u, UNIT_BEFORE, m, NULL, true);
if (s->sysv_enabled) {
int k;
if ((k = unit_add_dependency_by_name_inverse(u, UNIT_WANTS, m, NULL, true)) < 0)
r = k;
}
}
else
/* NB: SysV targets
* which are provided
* by a service are
* pulled in by the
* services, as an
* indication that the
* generic service is
* now available. This
* is strictly
* one-way. The
* targets do NOT pull
* in the SysV
* services! */
r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_WANTS, m, NULL, true);
if (r < 0)
log_error("[%s:%u] Failed to add LSB Provides name %s, ignoring: %s", path, line, m, strerror(-r));
@ -824,7 +829,7 @@ static int service_load_sysv_path(Service *s, const char *path) {
s->exec_context.std_output =
(s->meta.manager->sysv_console || s->exec_context.std_input == EXEC_INPUT_TTY)
? EXEC_OUTPUT_TTY : s->meta.manager->default_std_output;
s->exec_context.kill_mode = KILL_PROCESS_GROUP;
s->exec_context.kill_mode = KILL_PROCESS;
/* We use the long description only if
* no short description is set. */
@ -849,6 +854,12 @@ static int service_load_sysv_path(Service *s, const char *path) {
u->meta.description = d;
}
/* The priority that has been set in /etc/rcN.d/ hierarchies
* takes precedence over what is stored as default in the LSB
* header */
if (s->sysv_start_priority_from_rcnd >= 0)
s->sysv_start_priority = s->sysv_start_priority_from_rcnd;
u->meta.load_state = UNIT_LOADED;
r = 0;
@ -1013,7 +1024,7 @@ static int fsck_fix_order(Service *s) {
else
continue;
if (!(r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
if ((r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
return r;
}
@ -1130,7 +1141,7 @@ static int service_load(Unit *u) {
s->notify_access = NOTIFY_MAIN;
if (s->type == SERVICE_DBUS || s->bus_name)
if ((r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_DBUS_TARGET, NULL, true)) < 0)
if ((r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true)) < 0)
return r;
if (s->meta.default_dependencies)
@ -1581,8 +1592,8 @@ static int service_collect_fds(Service *s, int **fds, unsigned *n_fds) {
goto fail;
}
memcpy(t, rfds, rn_fds);
memcpy(t+rn_fds, cfds, cn_fds);
memcpy(t, rfds, rn_fds * sizeof(int));
memcpy(t+rn_fds, cfds, cn_fds * sizeof(int));
free(rfds);
free(cfds);
@ -1659,7 +1670,7 @@ static int service_spawn(
}
if (set_notify_socket)
if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=@%s", s->meta.manager->notify_socket) < 0) {
if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", s->meta.manager->notify_socket) < 0) {
r = -ENOMEM;
goto fail;
}
@ -1834,19 +1845,14 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) {
int sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? s->exec_context.kill_signal : SIGKILL;
if (s->main_pid > 0) {
if (kill_and_sigcont(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
-s->main_pid :
s->main_pid, sig) < 0 && errno != ESRCH)
if (kill_and_sigcont(s->main_pid, sig) < 0 && errno != ESRCH)
log_warning("Failed to kill main process %li: %m", (long) s->main_pid);
else
wait_for_exit = true;
}
if (s->control_pid > 0) {
if (kill_and_sigcont(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
-s->control_pid :
s->control_pid, sig) < 0 && errno != ESRCH)
if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
else
@ -1876,6 +1882,7 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) {
wait_for_exit = true;
set_free(pid_set);
pid_set = NULL;
}
}
@ -3010,8 +3017,8 @@ static int service_enumerate(Manager *m) {
if (de->d_name[0] == 'S') {
if (rcnd_table[i].type == RUNLEVEL_UP || rcnd_table[i].type == RUNLEVEL_SYSINIT) {
SERVICE(service)->sysv_start_priority =
MAX(a*10 + b, SERVICE(service)->sysv_start_priority);
SERVICE(service)->sysv_start_priority_from_rcnd =
MAX(a*10 + b, SERVICE(service)->sysv_start_priority_from_rcnd);
SERVICE(service)->sysv_enabled = true;
}
@ -3208,11 +3215,11 @@ static int service_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusErro
}
if (s->control_pid > 0)
if (kill(mode == KILL_PROCESS_GROUP ? -s->control_pid : s->control_pid, signo) < 0)
if (kill(s->control_pid, signo) < 0)
r = -errno;
if (s->main_pid > 0)
if (kill(mode == KILL_PROCESS_GROUP ? -s->main_pid : s->main_pid, signo) < 0)
if (kill(s->main_pid, signo) < 0)
r = -errno;
if (mode == KILL_CONTROL_GROUP) {

View File

@ -138,6 +138,7 @@ struct Service {
#ifdef HAVE_SYSV_COMPAT
bool sysv_has_lsb:1;
bool sysv_enabled:1;
int sysv_start_priority_from_rcnd;
int sysv_start_priority;
char *sysv_path;

View File

@ -96,125 +96,107 @@ static int killall(int sign) {
return n_processes;
}
static int send_signal(int sign) {
sigset_t mask, oldmask;
static void wait_for_children(int n_processes, sigset_t *mask) {
usec_t until;
assert(mask);
until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
for (;;) {
struct timespec ts;
int k;
usec_t n;
for (;;) {
pid_t pid = waitpid(-1, NULL, WNOHANG);
if (pid == 0)
break;
if (pid < 0 && errno == ECHILD)
return;
if (n_processes > 0)
if (--n_processes == 0)
return;
}
n = now(CLOCK_MONOTONIC);
if (n >= until)
return;
timespec_store(&ts, until - n);
if ((k = sigtimedwait(mask, NULL, &ts)) != SIGCHLD) {
if (k < 0 && errno != EAGAIN) {
log_error("sigtimedwait() failed: %m");
return;
}
if (k >= 0)
log_warning("sigtimedwait() returned unexpected signal.");
}
}
}
static void send_signal(int sign) {
sigset_t mask, oldmask;
int n_processes;
struct timespec ts;
assert_se(sigemptyset(&mask) == 0);
assert_se(sigaddset(&mask, SIGCHLD) == 0);
if (sigprocmask(SIG_BLOCK, &mask, &oldmask) != 0)
return -errno;
assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
if (kill(-1, SIGSTOP) < 0)
if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
log_warning("kill(-1, SIGSTOP) failed: %m");
n_processes = killall(sign);
if (kill(-1, SIGCONT) < 0)
if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
log_warning("kill(-1, SIGCONT) failed: %m");
if (n_processes <= 0)
goto finish;
until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
for (;;) {
int k;
usec_t n = now(CLOCK_MONOTONIC);
for (;;) {
pid_t pid = waitpid(-1, NULL, WNOHANG);
if (pid == 0)
break;
else if (pid < 0 && errno == ECHILD) {
n_processes = 0;
goto finish;
}
if (--n_processes == 0)
goto finish;
}
if (n >= until)
goto finish;
timespec_store(&ts, until - n);
if ((k = sigtimedwait(&mask, NULL, &ts)) != SIGCHLD) {
if (k >= 0)
log_warning("sigtimedwait() returned unexpected signal.");
if (k < 0 && errno != EAGAIN)
log_warning("sigtimedwait() failed: %m");
}
}
wait_for_children(n_processes, &mask);
finish:
sigprocmask(SIG_SETMASK, &oldmask, NULL);
return n_processes;
}
static int rescue_send_signal(int sign) {
static void ultimate_send_signal(int sign) {
sigset_t mask, oldmask;
usec_t until;
struct timespec ts;
int r;
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &mask, &oldmask) != 0)
return -errno;
assert_se(sigemptyset(&mask) == 0);
assert_se(sigaddset(&mask, SIGCHLD) == 0);
assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
if (kill(-1, SIGSTOP) < 0)
if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
log_warning("kill(-1, SIGSTOP) failed: %m");
r = kill(-1, sign);
if (r < 0)
log_warning("kill(-1, %d) failed: %m", sign);
if (r < 0 && errno != ESRCH)
log_warning("kill(-1, %s) failed: %m", signal_to_string(sign));
if (kill(-1, SIGCONT) < 0)
if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
log_warning("kill(-1, SIGCONT) failed: %m");
if (r < 0)
goto finish;
until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
for (;;) {
int k;
usec_t n = now(CLOCK_MONOTONIC);
for (;;) {
pid_t pid = waitpid(-1, NULL, WNOHANG);
if (pid == 0)
break;
else if (pid < 0 && errno == ECHILD)
goto finish;
}
if (n >= until)
goto finish;
timespec_store(&ts, until - n);
if ((k = sigtimedwait(&mask, NULL, &ts)) != SIGCHLD) {
if (k >= 0)
log_warning("sigtimedwait() returned unexpected signal.");
if (k < 0 && errno != EAGAIN)
log_warning("sigtimedwait() failed: %m");
}
}
wait_for_children(0, &mask);
finish:
sigprocmask(SIG_SETMASK, &oldmask, NULL);
return r;
}
int main(int argc, char *argv[]) {
int cmd, r;
unsigned retries;
bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
bool killed_everbody = false;
bool killed_everbody = false, in_container;
log_parse_environment();
log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
@ -232,6 +214,8 @@ int main(int argc, char *argv[]) {
goto error;
}
in_container = detect_container(NULL) > 0;
if (streq(argv[1], "reboot"))
cmd = RB_AUTOBOOT;
else if (streq(argv[1], "poweroff"))
@ -251,14 +235,13 @@ int main(int argc, char *argv[]) {
log_warning("Cannot lock process memory: %m");
log_info("Sending SIGTERM to remaining processes...");
r = send_signal(SIGTERM);
if (r < 0)
log_warning("Failed to send SIGTERM to remaining processes: %s", strerror(r));
send_signal(SIGTERM);
log_info("Sending SIGKILL to remaining processes...");
r = send_signal(SIGKILL);
if (r < 0)
log_warning("Failed to send SIGKILL to remaining processes: %s", strerror(r));
send_signal(SIGKILL);
if (in_container)
need_swapoff = false;
/* Unmount all mountpoints, swaps, and loopback devices */
for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
@ -325,8 +308,8 @@ int main(int argc, char *argv[]) {
}
log_warning("Cannot finalize remaining file systems and devices, trying to kill remaining processes.");
rescue_send_signal(SIGTERM);
rescue_send_signal(SIGKILL);
ultimate_send_signal(SIGTERM);
ultimate_send_signal(SIGKILL);
killed_everbody = true;
}
@ -338,6 +321,13 @@ int main(int argc, char *argv[]) {
execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, NULL);
/* If we are in a container, just exit, this will kill our
* container for good. */
if (in_container) {
log_error("Exiting container.");
exit(0);
}
sync();
if (cmd == LINUX_REBOOT_CMD_KEXEC) {

View File

@ -227,7 +227,7 @@ int main(int argc, char *argv[]) {
if ((pollfd[i].fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
log_error("timerfd_create(): %m");
failed = false;
failed = true;
}
}
@ -318,10 +318,10 @@ int main(int argc, char *argv[]) {
if (pollfd[FD_NOLOGIN_TIMER].revents) {
int e;
log_info("Creating /var/run/nologin, blocking further logins...");
log_info("Creating /run/nologin, blocking further logins...");
if ((e = write_one_line_file("/var/run/nologin", "System is going down.")) < 0)
log_error("Failed to create /var/run/nologin: %s", strerror(-e));
if ((e = write_one_line_file("/run/nologin", "System is going down.")) < 0)
log_error("Failed to create /run/nologin: %s", strerror(-e));
else
unlink_nologin = true;
@ -346,7 +346,7 @@ finish:
close_nointr_nofail(pollfd[i].fd);
if (unlink_nologin)
unlink("/var/run/nologin");
unlink("/run/nologin");
if (exec_shutdown) {
char sw[3];

Some files were not shown because too many files have changed in this diff Show More