diff --git a/Makefile-man.am b/Makefile-man.am index 5c289dd..a02ef73 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -63,6 +63,7 @@ MANPAGES += \ man/systemd-delta.1 \ man/systemd-detect-virt.1 \ man/systemd-efi-boot-generator.8 \ + man/systemd-escape.1 \ man/systemd-fsck@.service.8 \ man/systemd-fstab-generator.8 \ man/systemd-getty-generator.8 \ @@ -680,7 +681,8 @@ endif if ENABLE_COREDUMP MANPAGES += \ man/coredump.conf.5 \ - man/coredumpctl.1 + man/coredumpctl.1 \ + man/systemd-coredump.8 MANPAGES_ALIAS += \ # @@ -1594,12 +1596,14 @@ EXTRA_DIST += \ man/systemd-cat.xml \ man/systemd-cgls.xml \ man/systemd-cgtop.xml \ + man/systemd-coredump.xml \ man/systemd-cryptsetup-generator.xml \ man/systemd-cryptsetup@.service.xml \ man/systemd-debug-generator.xml \ man/systemd-delta.xml \ man/systemd-detect-virt.xml \ man/systemd-efi-boot-generator.xml \ + man/systemd-escape.xml \ man/systemd-fsck@.service.xml \ man/systemd-fstab-generator.xml \ man/systemd-getty-generator.xml \ diff --git a/Makefile.am b/Makefile.am index e238cde..764a4fd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -337,7 +337,8 @@ rootbin_PROGRAMS = \ systemd-notify \ systemd-ask-password \ systemd-tty-ask-password-agent \ - systemd-machine-id-setup + systemd-machine-id-setup \ + systemd-escape bin_PROGRAMS = \ systemd-cgls \ @@ -382,7 +383,6 @@ systemgenerator_PROGRAMS = \ dist_bashcompletion_DATA = \ shell-completion/bash/busctl \ shell-completion/bash/journalctl \ - shell-completion/bash/systemctl \ shell-completion/bash/systemd-analyze \ shell-completion/bash/systemd-cat \ shell-completion/bash/systemd-cgls \ @@ -394,8 +394,10 @@ dist_bashcompletion_DATA = \ shell-completion/bash/udevadm \ shell-completion/bash/kernel-install +nodist_bashcompletion_DATA = \ + shell-completion/bash/systemctl + dist_zshcompletion_DATA = \ - shell-completion/zsh/_systemctl \ shell-completion/zsh/_journalctl \ shell-completion/zsh/_udevadm \ shell-completion/zsh/_kernel-install \ @@ -406,13 +408,23 @@ dist_zshcompletion_DATA = \ shell-completion/zsh/_systemd-delta \ shell-completion/zsh/_systemd +nodist_zshcompletion_DATA = \ + shell-completion/zsh/_systemctl + +EXTRA_DIST += \ + shell-completion/bash/systemctl.in \ + shell-completion/zsh/_systemctl.in + +CLEANFILES += \ + $(nodist_bashcompletion_DATA) \ + $(nodist_zshcompletion_DATA) + dist_sysctl_DATA = \ sysctl.d/50-default.conf dist_systemunit_DATA = \ units/graphical.target \ units/multi-user.target \ - units/emergency.service \ units/emergency.target \ units/sysinit.target \ units/basic.target \ @@ -1712,6 +1724,7 @@ systemd_update_done_SOURCES = \ systemd_update_done_LDADD = \ libsystemd-internal.la \ + libsystemd-label.la \ libsystemd-shared.la # ------------------------------------------------------------------------------ @@ -2079,6 +2092,13 @@ systemd_cgroups_agent_LDADD = \ libsystemd-shared.la # ------------------------------------------------------------------------------ +systemd_escape_SOURCES = \ + src/escape/escape.c + +systemd_escape_LDADD = \ + libsystemd-shared.la + +# ----------------------------------------------------------------------------- systemctl_SOURCES = \ src/systemctl/systemctl.c @@ -3319,16 +3339,6 @@ typelibs_DATA = \ CLEANFILES += $(gir_DATA) $(typelibs_DATA) endif # HAVE_INTROSPECTION - -# move lib from $(libdir) to $(rootlibdir) and update devel link, if needed -libgudev-install-hook: - libname=libgudev-1.0.so && $(move-to-rootlibdir) - -libgudev-uninstall-hook: - rm -f $(DESTDIR)$(rootlibdir)/libgudev-1.0.so* - -INSTALL_EXEC_HOOKS += libgudev-install-hook -UNINSTALL_EXEC_HOOKS += libgudev-uninstall-hook endif EXTRA_DIST += \ @@ -4337,7 +4347,7 @@ nodist_systemunit_DATA += \ units/systemd-timesyncd.service GENERAL_ALIASES += \ - $(systemunitdir)/systemd-timesyncd.service $(pkgsysconfdir)/system/multi-user.target.wants/systemd-timesyncd.service + $(systemunitdir)/systemd-timesyncd.service $(pkgsysconfdir)/system/sysinit.target.wants/systemd-timesyncd.service EXTRA_DIST += \ units/systemd-timesyncd.service.in @@ -5189,6 +5199,9 @@ src/core/macros.%: src/core/macros.%.in src/%.policy.in: src/%.policy.in.in $(SED_PROCESS) +shell-completion/%: shell-completion/%.in + $(SED_PROCESS) + %.rules: %.rules.in $(SED_PROCESS) @@ -5216,7 +5229,7 @@ units/user/%: units/%.m4 $(AM_V_M4)$(M4) -P $(M4_DEFINES) -DFOR_USER=1 < $< > $@ if ENABLE_POLKIT -dist_polkitpolicy_DATA = \ +nodist_polkitpolicy_DATA = \ $(polkitpolicy_files) \ $(polkitpolicy_in_in_files:.policy.in.in=.policy) endif diff --git a/configure.ac b/configure.ac index ae88382..8925eb5 100644 --- a/configure.ac +++ b/configure.ac @@ -310,7 +310,9 @@ AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, LO_FLAGS_PARTSCAN] #include ]]) -AC_CHECK_DECLS([IFLA_PHYS_PORT_ID, +AC_CHECK_DECLS([IFLA_MACVLAN_FLAGS, + IFLA_VTI_REMOTE, + IFLA_PHYS_PORT_ID, IFLA_BOND_AD_INFO, IFLA_VLAN_PROTOCOL, IFLA_VXLAN_LOCAL6, diff --git a/man/coredumpctl.xml b/man/coredumpctl.xml index 73d1b84..327ef6e 100644 --- a/man/coredumpctl.xml +++ b/man/coredumpctl.xml @@ -210,6 +210,8 @@ See Also + systemd-coredump8, + coredump.conf5, systemd-journald.service8, gdb1 diff --git a/man/crypttab.xml b/man/crypttab.xml index 9dbf154..d658a6f 100644 --- a/man/crypttab.xml +++ b/man/crypttab.xml @@ -319,6 +319,21 @@ + + + Specifies how long + systemd should wait for a device to + show up before giving up on the + entry. The argument is a time in + seconds or explicitly specifified + units of s, + min, + h, + ms. + + + + The encrypted block device will diff --git a/man/file-hierarchy.xml b/man/file-hierarchy.xml index ed6e0e9..408042e 100644 --- a/man/file-hierarchy.xml +++ b/man/file-hierarchy.xml @@ -190,7 +190,9 @@ should prefer using the directory specified in it over directly referencing - /tmp (see environ7 for details). + /tmp (see environ7 + and + IEEE Std 1003.1 for details). @@ -461,7 +463,8 @@ set they should prefer using the directory specified in it over directly referencing - /var/tmp (see environ7 for details). + /var/tmp (see environ7 + for details). diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml index 71973fd..13e5bd5 100644 --- a/man/hostnamectl.xml +++ b/man/hostnamectl.xml @@ -102,14 +102,6 @@ - - - - Acquire privileges via PolicyKit - before executing the operation. - - - @@ -149,13 +141,14 @@ - set-hostname [NAME] + set-hostname NAME Set the system - hostname. By default, this will alter - the pretty, the static, and the - transient hostname alike; however, if - one or more of + hostname to + NAME. By + default, this will alter the pretty, + the static, and the transient hostname + alike; however, if one or more of , , are used, @@ -176,54 +169,61 @@ the hostname string is not done if only the transient and/or static host names are set, and the pretty host - name is left untouched. Pass the empty - string as the - hostname to reset the selected - hostnames to their default (usually + name is left untouched. + + Pass the empty string + as the hostname to + reset the selected hostnames to their + default (usually localhost). - set-icon-name [NAME] + set-icon-name NAME Set the system icon - name. The icon name is used by some - graphical applications to visualize - this host. The icon name should follow - the NAME. The + icon name is used by some graphical + applications to visualize this host. + The icon name should follow the Icon - Naming Specification. Pass an - empty string to this operation to - reset the icon name to the default - value, which is determined from chassis - type (see below) and possibly other + Naming Specification. + + Pass an empty string to reset + the icon name to the default value, + which is determined from chassis type + (see below) and possibly other parameters. - set-chassis [TYPE] + set-chassis TYPE - Set the chassis - type. The chassis type is used by some + Set the chassis type + to TYPE. + The chassis type is used by some graphical applications to visualize - the host or alter user - interaction. Currently, the following - chassis types are defined: + the host or alter user interaction. + Currently, the following chassis types + are defined: desktop, laptop, server, tablet, - handset, as well as + handset, + watch, as well as the special chassis types vm and container for virtualized systems that lack an - immediate physical chassis. Pass an - empty string to this operation to - reset the chassis type to the default - value which is determined from the - firmware and possibly other - parameters. + immediate physical chassis. + + Pass an empty string to reset + the chassis type to the default value + which is determined from the firmware + and possibly other parameters. + diff --git a/man/journalctl.xml b/man/journalctl.xml index 78fc6f6..de7741c 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -908,6 +908,7 @@ systemd1, systemd-journald.service8, systemctl1, + coredumpctl1, systemd.journal-fields7, journald.conf5 diff --git a/man/localectl.xml b/man/localectl.xml index c2e79a2..9c32c79 100644 --- a/man/localectl.xml +++ b/man/localectl.xml @@ -90,14 +90,6 @@ - - - - Acquire privileges via PolicyKit - before executing the operation. - - - If diff --git a/man/machine-info.xml b/man/machine-info.xml index 7448e68..244e9b6 100644 --- a/man/machine-info.xml +++ b/man/machine-info.xml @@ -138,7 +138,8 @@ laptop, server, tablet, - handset, as well as + handset, + watch, as well as the special chassis types vm and container for diff --git a/man/sd_journal_get_cutoff_realtime_usec.xml b/man/sd_journal_get_cutoff_realtime_usec.xml index 6df4b26..ef987d8 100644 --- a/man/sd_journal_get_cutoff_realtime_usec.xml +++ b/man/sd_journal_get_cutoff_realtime_usec.xml @@ -74,25 +74,29 @@ Description sd_journal_get_cutoff_realtime_usec() - gets the realtime (wallclock) timestamps of the first - and last entries accessible in the journal. It takes - three arguments: the journal context object and two - pointers to 64-bit unsigned integers to store the - timestamps in. The timestamps are in microseconds - since the epoch, + retrieves the realtime (wallclock) timestamps of the + first and last entries accessible in the journal. It + takes three arguments: the journal context object + j and two pointers + from and + to pointing at 64-bit unsigned + integers to store the timestamps in. The timestamps + are in microseconds since the epoch, i.e. CLOCK_REALTIME. Either one of the two timestamp arguments may be passed as NULL in case the timestamp is not needed, but not both. sd_journal_get_cutoff_monotonic_usec() - gets the monotonic timestamps of the first and last - entries accessible in the journal. It takes three - arguments: the journal context object, a 128-bit - identifier for the boot, and two pointers to 64-bit - unsigned integers to store the timestamps. The - timestamps are in microseconds since boot-up of the - specific boot, + retrieves the monotonic timestamps of the first and + last entries accessible in the journal. It takes three + arguments: the journal context object + j, a 128-bit identifier for the + boot boot_id, and two pointers + to 64-bit unsigned integers to store the timestamps, + from and + to. The timestamps are in + microseconds since boot-up of the specific boot, i.e. CLOCK_MONOTONIC. Since the monotonic clock begins new with every reboot it only defines a well-defined point in time when used @@ -113,6 +117,12 @@ sd_journal_get_cutoff_monotonic_usec() return 1 on success, 0 if not suitable entries are in the journal or a negative errno-style error code. + + Locations pointed to by parameters + from and + to will be set only if the + return value is positive, and obviously, the + parameters are non-null. diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml new file mode 100644 index 0000000..b83b278 --- /dev/null +++ b/man/systemd-coredump.xml @@ -0,0 +1,105 @@ + + + + + + + + + systemd-coredump + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + systemd-coredump + 8 + + + + systemd-coredump + Log and store core dumps + + + + /usr/lib/systemd/systemd-coredump + + + + Description + + systemd-coredump can be used as a helper + binary by the kernel when a user space program receives a fatal + signal and dumps core. For it to be used in this capacity, it must + be specified by the + kernel.core_pattern sysctl8 + setting. Systemd installs + /usr/lib/sysctl.d/50-coredump.conf which + configures kernel.core_pattern to invoke + systemd-coredump. This file may be masked or + overriden to use a different setting following normal + sysctl.d5 rules. + + The behaviour of a specific program upon reception of a + signal is governed by a few factors which are described in detail + in core5. + In particular, the coredump will only be processed when the + related resource limits are high enough. For programs started by + systemd those may be set using + LimitCore= (see + systemd.exec5). + + + systemd-coredump will log the coredump + including a backtrace if possible, and store the core (contents of + process' memory contents) in an external file on disk in + /var/lib/systemd/coredump, or directly in + the journal. This behaviour may be modified using + coredump.conf5. + + Apart from the + journalctl1 + log viewer, + coredumpctl1 + may be used to list and extract coredumps. + + + + See Also + + coredump.conf5, + coredumpctl1, + systemd-journald.service8, + core5, + sysctl.d5, + systemd-sysctl.service8. + + + diff --git a/man/systemd-escape.xml b/man/systemd-escape.xml new file mode 100644 index 0000000..b2a4a9c --- /dev/null +++ b/man/systemd-escape.xml @@ -0,0 +1,193 @@ + + + + + + + + + systemd-escape + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + systemd-escape + 1 + + + + systemd-escape + Escape strings for usage in system unit names + + + + + systemd-escape OPTIONS STRING + + + + + Description + + systemd-escape may be used to + escape strings for inclusion in systemd unit + names. The command may be used to escape and to undo + escaping of strings. + + The command takes any number of strings on the + command line, and will process them individually, one + after the other. It will output them separated by + spaces to stdout. + + By default this command will escape the strings + passed, unless is passed + which results in the inverse operation being + applied. If a special mode + of escaping is applied instead, which assumes a string + to be already escaped but will escape everything that + appears obviously non-escaped. + + + + Options + + The following options are understood: + + + + + + Appends the specified + unit type suffix to the escaped + string. Takes one of the unit types + supported by systemd, such as + .service or + .mount. May not be + used in conjunction with + , + or + . + + + + + + Inserts the escaped + strings in a unit name template. Takes + a unit name template such as + foobar@.service + May not be used in conjunction with + , + or + . + + + + + + + When escaping or + unescaping a string, assume it refers + to a file system path. This enables + special processing of the initial + / of the + path. + + + + + + Instead of escaping + the specified strings, undo the + escaping, reversing the operation. May + not be used in conjunction with + , + or + . + + + + + + Like + , but only + escape characters that are obviously + not escaped yet, and possibly + automatically append an appropriate + unit type suffix to the string. May + not be used in conjunction with + , + or + . + + + + + + + + + + Examples + + Escape a single string: + $ systemd-escape 'Hallöchen, Meister' +Hall\xc3\xb6chen\x2c\x20Meister + + To undo escaping on a single string: + $ systemd-escape -u 'Hall\xc3\xb6chen\x2c\x20Meister' +Hallöchen, Meister + + To generate the mount unit for a path: + $ systemd-escape -p --suffix=mount "/tmp//waldi/foobar/" +tmp-waldi-foobar.mount + + To generate instance names of three strings + $ systemd-escape --template=systemd-nspawn@.service 'My Container 1' 'containerb' 'container/III' +systemd-nspawn@My\x20Container\x201.service systemd-nspawn@containerb.service systemd-nspawn@container-III.service + + + + Exit status + + On success, 0 is returned, a non-zero failure + code otherwise. + + + + See Also + + systemd1, + systemctl1 + + + + diff --git a/man/systemd-journald.service.xml b/man/systemd-journald.service.xml index 7ac73ed..eb16118 100644 --- a/man/systemd-journald.service.xml +++ b/man/systemd-journald.service.xml @@ -248,6 +248,7 @@ journald.conf5, systemd.journal-fields7, sd-journal3, + systemd-coredump8, setfacl1, pydoc systemd.journal. diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index c90bd8f..347f80e 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -60,7 +60,10 @@ Virtual Network Device files must have the extension .netdev; other extensions are ignored. Virtual - network devices are created as soon as networkd is started. + network devices are created as soon as networkd is started. If a netdev + with the specified name already exists, networkd will use that as-is + rather than create its own. Note that the settings of the pre-existing + netdev will not be changed by networkd. The .netdev files are read from the files located in the system network directory /usr/lib/systemd/network, @@ -163,7 +166,8 @@ macvlan, vxlan, ipip, gre, sit, vti, - veth, and dummy + veth, tun, + tap and dummy are supported. This option is compulsory. diff --git a/man/systemd.time.xml b/man/systemd.time.xml index 0706cdf..02431a5 100644 --- a/man/systemd.time.xml +++ b/man/systemd.time.xml @@ -243,12 +243,16 @@ The special expressions hourly, daily, - monthly and weekly - may be used as calendar events which refer to - *-*-* *:00:00, *-*-* - 00:00:00, *-*-01 00:00:00 and - Mon *-*-* 00:00:00, - respectively. + monthly, weekly, + and yearly or + annually may be used as calendar + events which refer to + *-*-* *:00:00, + *-*-* 00:00:00, + *-*-01 00:00:00, + Mon *-*-* 00:00:00, and + *-01-01 00:00:00 respectively. + Examples for valid timestamps and their normalized form: @@ -277,6 +281,8 @@ Wed-Sat,Tue 12-10-15 1:2:3 → Tue-Sat 2012-10-15 01:02:03 daily → *-*-* 00:00:00 monthly → *-*-01 00:00:00 weekly → Mon *-*-* 00:00:00 + yearly → *-01-01 00:00:00 + annually → *-01-01 00:00:00 *:2/3 → *-*-* *:02/3:00 Calendar events are used by timer units, see diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 960fb90..e66be4e 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -74,6 +74,8 @@ $HOME/.config/systemd/user/* /etc/systemd/user/* /run/systemd/user/* +$XDG_DATA_HOME/systemd/user/* +$HOME/.local/share/systemd/user/* /usr/lib/systemd/user/* ... @@ -339,8 +341,16 @@ Runtime units + $XDG_DATA_HOME/systemd/user + Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is set) + + + $HOME/.local/share/systemd/user + Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is not set) + + /usr/lib/systemd/user - Units of installed packages + Units of packages that have been installed system-wide @@ -931,7 +941,9 @@ x86, x86-64, ppc, + ppc-le, ppc64, + ppc64-le, ia64, parisc, parisc64, @@ -940,7 +952,9 @@ sparc, sparc64, mips, + mips-le, mips64, + mips64-le, alpha, arm, arm-be, @@ -948,7 +962,9 @@ arm64-be, sh, sh64, - m86k to test + m86k, + tilegx, + cris to test against a specific architecture. The architecture is determined from the information returned by @@ -979,12 +995,12 @@ virtualization solution, or one of qemu, kvm, + zvm, vmware, microsoft, oracle, xen, bochs, - chroot, uml, openvz, lxc, diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml index 549b3f6..1e079b2 100644 --- a/man/sysusers.d.xml +++ b/man/sysusers.d.xml @@ -53,32 +53,28 @@ Description systemd-sysusers uses the - files from /usr/lib/sysusers.d/ + files from sysusers.d directory to create system users and groups at package - installation or boot time. This tool may be used for - allocating system users and groups only, it is not + installation or boot time. This tool may be used to + allocate system users and groups only, it is not useful for creating non-system users and groups, as it - accessed /etc/passwd and + accesses /etc/passwd and /etc/group directly, bypassing - any more complex user database, for example any + any more complex user databases, for example any database involving NIS or LDAP. - - File Format - - Each file shall be named in the style of - package.conf. + Configuration Format - All files are sorted by their filename in - lexicographic order, regardless of which of the - directories they reside in. If multiple files specify - the same user or group, the entry in the file with the - lexicographically earliest name will be applied, all - all other conflicting entries will be logged as - errors. Users and groups are - processed in the order they are listed. + Each configuration file shall be named in the + style of + package.conf + or + package-part.conf. + The second variant should be used when it is desirable + to make it easy to override just this part of + configuration. The file format is one line per user or group containing name, ID and GECOS field description: @@ -106,7 +102,7 @@ m authd input group will be set to the group bearing the same name. The user's shell will be set to - /sbin/login, + /sbin/nologin, the home directory to /. The account will be created @@ -142,7 +138,7 @@ m authd input Name The name field specifies the user or - group name. It should be be shorter than 256 + group name. It should be be shorter than 31 characters and avoid any non-ASCII characters, and not begin with a numeric character. It is strongly recommended to pick user and group @@ -193,10 +189,39 @@ m authd input + Overriding vendor configuration + + Note that systemd-sysusers + will do nothing if the specified users or groups + already exist, so normally there no reason to override + sysusers.d vendor configuration, + except to block certain users or groups from being + created. + + Files in /etc/sysusers.d + override files with the same name in + /usr/lib/sysusers.d and + /run/sysusers.d. Files in + /run/sysusers.d override files + with the same name in + /usr/lib/sysusers.d. The scheme is the same as for + tmpfiles.d5, + except for the directory name. + + If the administrator wants to disable a + configuration file supplied by the vendor, the + recommended way is to place a symlink to + /dev/null in + /etc/sysusers.d/ bearing the + same filename. + + + See Also systemd1, - systemd-sysusers8 + systemd-sysusers8, + tmpfiles.d5 diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in index db72373..c3ef81b 100644 --- a/rules/99-systemd.rules.in +++ b/rules/99-systemd.rules.in @@ -43,7 +43,7 @@ SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsys SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k" SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target" -ENV{ID_SMARTCARD_READER}=="*?", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target" +ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target" SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" diff --git a/shell-completion/bash/.gitignore b/shell-completion/bash/.gitignore new file mode 100644 index 0000000..016e09d --- /dev/null +++ b/shell-completion/bash/.gitignore @@ -0,0 +1 @@ +/systemctl diff --git a/shell-completion/bash/hostnamectl b/shell-completion/bash/hostnamectl index 9c75da9..22f8f06 100644 --- a/shell-completion/bash/hostnamectl +++ b/shell-completion/bash/hostnamectl @@ -39,6 +39,7 @@ _hostnamectl() { [STANDALONE]='status' [ICONS]='set-icon-name' [NAME]='set-hostname' + [CHASSIS]='set-chassis' ) for ((i=0; i < COMP_CWORD; i++)); do @@ -50,6 +51,8 @@ _hostnamectl() { if [[ -z $verb ]]; then comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[CHASSIS]}; then + comps='desktop laptop server tablet handset watch vm container' elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[ICONS]} ${VERBS[NAME]}; then comps='' fi diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl index e4b2f4a..14dcd22 100644 --- a/shell-completion/bash/journalctl +++ b/shell-completion/bash/journalctl @@ -35,6 +35,8 @@ __journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC} _UDEV_{SYSNAME,DEVNODE,DEVLINK} __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP) +__syslog_priorities=(emerg alert crit err warning notice info debug) + _journalctl() { local field_vals= cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( @@ -44,8 +46,8 @@ _journalctl() { --no-tail -q --quiet --setup-keys --this-boot --verify --version --list-catalog --update-catalog --list-boots' [ARG]='-b --boot --this-boot -D --directory --file -F --field - -o --output -u --unit --user-unit' - [ARGUNKNOWN]='-c --cursor --interval -n --lines -p --priority --since --until + -o --output -u --unit --user-unit -p --priority' + [ARGUNKNOWN]='-c --cursor --interval -n --lines --since --until --verify-key' ) @@ -68,6 +70,9 @@ _journalctl() { --field|-F) comps=${__journal_fields[*]} ;; + --priority|-p) + comps=${__syslog_priorities[*]} + ;; --unit|-u) comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null) ;; diff --git a/shell-completion/bash/systemctl b/shell-completion/bash/systemctl deleted file mode 100644 index e1c8420..0000000 --- a/shell-completion/bash/systemctl +++ /dev/null @@ -1,226 +0,0 @@ -# systemctl(1) completion -*- shell-script -*- -# -# This file is part of systemd. -# -# Copyright 2010 Ran Benita -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# systemd is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with systemd; If not, see . - -__systemctl() { - local mode=$1; shift 1 - systemctl $mode --full --no-legend "$@" -} - -__systemd_properties() { - local mode=$1 - { __systemctl -a $mode show; - systemd --dump-configuration-items; } | - while IFS='=' read -r key value; do - [[ $value ]] && echo "$key" - done -} - -__contains_word () { - local w word=$1; shift - for w in "$@"; do - [[ $w = "$word" ]] && return - done -} - -__filter_units_by_property () { - local mode=$1 property=$2 value=$3 ; shift 3 - local units=("$@") - local props - IFS=$'\n' read -rd '' -a props < \ - <(__systemctl $mode show --property "$property" -- "${units[@]}") - for ((i=0; $i < ${#units[*]}; i++)); do - if [[ "${props[i]}" = "$property=$value" ]]; then - echo " ${units[i]}" - fi - done -} - -__get_all_units () { __systemctl $1 list-units --all \ - | { while read -r a b; do echo " $a"; done; }; } -__get_active_units () { __systemctl $1 list-units \ - | { while read -r a b; do echo " $a"; done; }; } -__get_startable_units () { __systemctl $1 list-units --all -t service,timer,socket,mount,automount,path,snapshot,swap \ - | { while read -r a b c d; do [[ $c == "inactive" || $c == "failed" ]] && echo " $a"; done; }; } -__get_failed_units () { __systemctl $1 list-units \ - | { while read -r a b c d; do [[ $c == "failed" ]] && echo " $a"; done; }; } -__get_enabled_units () { __systemctl $1 list-unit-files \ - | { while read -r a b c ; do [[ $b == "enabled" ]] && echo " $a"; done; }; } -__get_disabled_units () { __systemctl $1 list-unit-files \ - | { while read -r a b c ; do [[ $b == "disabled" ]] && echo " $a"; done; }; } -__get_masked_units () { __systemctl $1 list-unit-files \ - | { while read -r a b c ; do [[ $b == "masked" ]] && echo " $a"; done; }; } - -_systemctl () { - local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} - local i verb comps mode - - local -A OPTS=( - [STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full -l --global - --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall - --quiet -q --privileged -P --system --user --version --runtime --recursive -r' - [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --root' - ) - - if __contains_word "--user" ${COMP_WORDS[*]}; then - mode=--user - else - mode=--system - fi - - if __contains_word "$prev" ${OPTS[ARG]}; then - case $prev in - --signal|-s) - comps=$(compgen -A signal) - ;; - --type|-t) - comps='automount device mount path service snapshot socket swap target timer' - ;; - --state) - comps='loaded not-found stub - active inactive - dead elapsed exited listening mounted plugged running waiting' - ;; - --kill-who) - comps='all control main' - ;; - --root) - comps=$(compgen -A directory -- "$cur" ) - compopt -o filenames - ;; - --host|-H) - comps=$(compgen -A hostname) - ;; - --property|-p) - comps=$(__systemd_properties $mode) - ;; - esac - COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) - return 0 - fi - - if [[ "$cur" = -* ]]; then - COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) - return 0 - fi - - local -A VERBS=( - [ALL_UNITS]='is-active is-failed is-enabled status show cat mask preset help list-dependencies' - [ENABLED_UNITS]='disable' - [DISABLED_UNITS]='enable' - [REENABLABLE_UNITS]='reenable' - [FAILED_UNITS]='reset-failed' - [STARTABLE_UNITS]='start' - [STOPPABLE_UNITS]='stop condstop kill try-restart condrestart' - [ISOLATABLE_UNITS]='isolate' - [RELOADABLE_UNITS]='reload condreload reload-or-try-restart force-reload' - [RESTARTABLE_UNITS]='restart reload-or-restart' - [MASKED_UNITS]='unmask' - [JOBS]='cancel' - [SNAPSHOTS]='delete' - [ENVS]='set-environment unset-environment' - [STANDALONE]='daemon-reexec daemon-reload default - emergency exit halt hibernate hybrid-sleep kexec list-jobs - list-sockets list-timers list-units list-unit-files poweroff - reboot rescue show-environment suspend get-default' - [NAME]='snapshot' - [FILE]='link' - [TARGETS]='set-default' - ) - - for ((i=0; i < COMP_CWORD; i++)); do - if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && - ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then - verb=${COMP_WORDS[i]} - break - fi - done - - if [[ -z $verb ]]; then - comps="${VERBS[*]}" - - elif __contains_word "$verb" ${VERBS[ALL_UNITS]}; then - comps=$( __get_all_units $mode ) - - elif __contains_word "$verb" ${VERBS[ENABLED_UNITS]}; then - comps=$( __get_enabled_units $mode ) - - elif __contains_word "$verb" ${VERBS[DISABLED_UNITS]}; then - comps=$( __get_disabled_units $mode ) - - elif __contains_word "$verb" ${VERBS[REENABLABLE_UNITS]}; then - comps=$( __get_disabled_units $mode; - __get_enabled_units $mode ) - - elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then - comps=$( __filter_units_by_property $mode CanStart yes \ - $( __get_startable_units $mode)) - - elif __contains_word "$verb" ${VERBS[RESTARTABLE_UNITS]}; then - comps=$( __filter_units_by_property $mode CanStart yes \ - $( __get_all_units $mode \ - | while read -r line; do \ - [[ "$line" =~ \.(device|snapshot|socket|timer)$ ]] || echo " $line"; \ - done )) - - elif __contains_word "$verb" ${VERBS[STOPPABLE_UNITS]}; then - comps=$( __filter_units_by_property $mode CanStop yes \ - $( __get_active_units $mode ) ) - - elif __contains_word "$verb" ${VERBS[RELOADABLE_UNITS]}; then - comps=$( __filter_units_by_property $mode CanReload yes \ - $( __get_active_units $mode ) ) - - elif __contains_word "$verb" ${VERBS[ISOLATABLE_UNITS]}; then - comps=$( __filter_units_by_property $mode AllowIsolate yes \ - $( __get_all_units $mode ) ) - - elif __contains_word "$verb" ${VERBS[FAILED_UNITS]}; then - comps=$( __get_failed_units $mode ) - - elif __contains_word "$verb" ${VERBS[MASKED_UNITS]}; then - comps=$( __get_masked_units $mode ) - - elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[NAME]}; then - comps='' - - elif __contains_word "$verb" ${VERBS[JOBS]}; then - comps=$( __systemctl $mode list-jobs | { while read -r a b; do echo " $a"; done; } ) - - elif __contains_word "$verb" ${VERBS[SNAPSHOTS]}; then - comps=$( __systemctl $mode list-units --type snapshot --full --all \ - | { while read -r a b; do echo " $a"; done; } ) - - elif __contains_word "$verb" ${VERBS[ENVS]}; then - comps=$( __systemctl $mode show-environment \ - | while read -r line; do echo " ${line%%=*}=";done ) - compopt -o nospace - - elif __contains_word "$verb" ${VERBS[FILE]}; then - comps=$( compgen -A file -- "$cur" ) - compopt -o filenames - elif __contains_word "$verb" ${VERBS[TARGETS]}; then - comps=$( __systemctl $mode list-unit-files --type target --full --all \ - | { while read -r a b; do echo " $a"; done; } ) - fi - - COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) - return 0 -} - -complete -F _systemctl systemctl diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in new file mode 100644 index 0000000..4beec4e --- /dev/null +++ b/shell-completion/bash/systemctl.in @@ -0,0 +1,226 @@ +# systemctl(1) completion -*- shell-script -*- +# +# This file is part of systemd. +# +# Copyright 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__systemctl() { + local mode=$1; shift 1 + systemctl $mode --full --no-legend "$@" +} + +__systemd_properties() { + local mode=$1 + { __systemctl $mode show --all; + @rootlibexecdir@/systemd --dump-configuration-items; } | + while IFS='=' read -r key value; do + [[ $value ]] && echo "$key" + done +} + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__filter_units_by_property () { + local mode=$1 property=$2 value=$3 ; shift 3 + local units=("$@") + local props + IFS=$'\n' read -rd '' -a props < \ + <(__systemctl $mode show --property "$property" -- "${units[@]}") + for ((i=0; $i < ${#units[*]}; i++)); do + if [[ "${props[i]}" = "$property=$value" ]]; then + echo " ${units[i]}" + fi + done +} + +__get_all_units () { __systemctl $1 list-units --all \ + | { while read -r a b; do echo " $a"; done; }; } +__get_active_units () { __systemctl $1 list-units \ + | { while read -r a b; do echo " $a"; done; }; } +__get_startable_units () { __systemctl $1 list-units --all -t service,timer,socket,mount,automount,path,snapshot,swap \ + | { while read -r a b c d; do [[ $c == "inactive" || $c == "failed" ]] && echo " $a"; done; }; } +__get_failed_units () { __systemctl $1 list-units \ + | { while read -r a b c d; do [[ $c == "failed" ]] && echo " $a"; done; }; } +__get_enabled_units () { __systemctl $1 list-unit-files \ + | { while read -r a b c ; do [[ $b == "enabled" ]] && echo " $a"; done; }; } +__get_disabled_units () { __systemctl $1 list-unit-files \ + | { while read -r a b c ; do [[ $b == "disabled" ]] && echo " $a"; done; }; } +__get_masked_units () { __systemctl $1 list-unit-files \ + | { while read -r a b c ; do [[ $b == "masked" ]] && echo " $a"; done; }; } + +_systemctl () { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps mode + + local -A OPTS=( + [STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full -l --global + --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall + --quiet -q --privileged -P --system --user --version --runtime --recursive -r' + [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --root' + ) + + if __contains_word "--user" ${COMP_WORDS[*]}; then + mode=--user + else + mode=--system + fi + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --signal|-s) + comps=$(compgen -A signal) + ;; + --type|-t) + comps='automount device mount path service snapshot socket swap target timer' + ;; + --state) + comps='loaded not-found stub + active inactive + dead elapsed exited listening mounted plugged running waiting' + ;; + --kill-who) + comps='all control main' + ;; + --root) + comps=$(compgen -A directory -- "$cur" ) + compopt -o filenames + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --property|-p) + comps=$(__systemd_properties $mode) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [ALL_UNITS]='is-active is-failed is-enabled status show cat mask preset help list-dependencies' + [ENABLED_UNITS]='disable' + [DISABLED_UNITS]='enable' + [REENABLABLE_UNITS]='reenable' + [FAILED_UNITS]='reset-failed' + [STARTABLE_UNITS]='start' + [STOPPABLE_UNITS]='stop condstop kill try-restart condrestart' + [ISOLATABLE_UNITS]='isolate' + [RELOADABLE_UNITS]='reload condreload reload-or-try-restart force-reload' + [RESTARTABLE_UNITS]='restart reload-or-restart' + [MASKED_UNITS]='unmask' + [JOBS]='cancel' + [SNAPSHOTS]='delete' + [ENVS]='set-environment unset-environment' + [STANDALONE]='daemon-reexec daemon-reload default + emergency exit halt hibernate hybrid-sleep kexec list-jobs + list-sockets list-timers list-units list-unit-files poweroff + reboot rescue show-environment suspend get-default' + [NAME]='snapshot' + [FILE]='link' + [TARGETS]='set-default' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps="${VERBS[*]}" + + elif __contains_word "$verb" ${VERBS[ALL_UNITS]}; then + comps=$( __get_all_units $mode ) + + elif __contains_word "$verb" ${VERBS[ENABLED_UNITS]}; then + comps=$( __get_enabled_units $mode ) + + elif __contains_word "$verb" ${VERBS[DISABLED_UNITS]}; then + comps=$( __get_disabled_units $mode ) + + elif __contains_word "$verb" ${VERBS[REENABLABLE_UNITS]}; then + comps=$( __get_disabled_units $mode; + __get_enabled_units $mode ) + + elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then + comps=$( __filter_units_by_property $mode CanStart yes \ + $( __get_startable_units $mode)) + + elif __contains_word "$verb" ${VERBS[RESTARTABLE_UNITS]}; then + comps=$( __filter_units_by_property $mode CanStart yes \ + $( __get_all_units $mode \ + | while read -r line; do \ + [[ "$line" =~ \.(device|snapshot|socket|timer)$ ]] || echo " $line"; \ + done )) + + elif __contains_word "$verb" ${VERBS[STOPPABLE_UNITS]}; then + comps=$( __filter_units_by_property $mode CanStop yes \ + $( __get_active_units $mode ) ) + + elif __contains_word "$verb" ${VERBS[RELOADABLE_UNITS]}; then + comps=$( __filter_units_by_property $mode CanReload yes \ + $( __get_active_units $mode ) ) + + elif __contains_word "$verb" ${VERBS[ISOLATABLE_UNITS]}; then + comps=$( __filter_units_by_property $mode AllowIsolate yes \ + $( __get_all_units $mode ) ) + + elif __contains_word "$verb" ${VERBS[FAILED_UNITS]}; then + comps=$( __get_failed_units $mode ) + + elif __contains_word "$verb" ${VERBS[MASKED_UNITS]}; then + comps=$( __get_masked_units $mode ) + + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[NAME]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[JOBS]}; then + comps=$( __systemctl $mode list-jobs | { while read -r a b; do echo " $a"; done; } ) + + elif __contains_word "$verb" ${VERBS[SNAPSHOTS]}; then + comps=$( __systemctl $mode list-units --type snapshot --full --all \ + | { while read -r a b; do echo " $a"; done; } ) + + elif __contains_word "$verb" ${VERBS[ENVS]}; then + comps=$( __systemctl $mode show-environment \ + | while read -r line; do echo " ${line%%=*}=";done ) + compopt -o nospace + + elif __contains_word "$verb" ${VERBS[FILE]}; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + elif __contains_word "$verb" ${VERBS[TARGETS]}; then + comps=$( __systemctl $mode list-unit-files --type target --full --all \ + | { while read -r a b; do echo " $a"; done; } ) + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemctl systemctl diff --git a/shell-completion/zsh/.gitignore b/shell-completion/zsh/.gitignore new file mode 100644 index 0000000..75f13ad --- /dev/null +++ b/shell-completion/zsh/.gitignore @@ -0,0 +1 @@ +/_systemctl diff --git a/shell-completion/zsh/_hostnamectl b/shell-completion/zsh/_hostnamectl index 7effa04..be86876 100644 --- a/shell-completion/zsh/_hostnamectl +++ b/shell-completion/zsh/_hostnamectl @@ -1,5 +1,30 @@ #compdef hostnamectl +_hostnamectl_set-hostname() { + if (( CURRENT <= 3 )); then + _message "new hostname" + else + _message "no more options" + fi +} + +_hostnamectl_set-icon-name() { + if (( CURRENT <= 3 )); then + _message "new icon name" + else + _message "no more options" + fi +} + +_hostnamectl_set-chassis() { + if (( CURRENT <= 3 )); then + _chassis=( desktop laptop server tablet handset watch vm container ) + _describe chassis _chassis + else + _message "no more options" + fi +} + _hostnamectl_command() { local -a _hostnamectl_cmds _hostnamectl_cmds=( @@ -14,8 +39,11 @@ _hostnamectl_command() { local curcontext="$curcontext" cmd="${${_hostnamectl_cmds[(r)$words[1]:*]%%:*}}" if (( $#cmd )); then - [[ $cmd == status ]] && msg="no options" || msg="options for $cmd" - _message "$msg" + if [[ $cmd == status ]]; then + _message "no options" + else + _hostnamectl_$cmd + fi else _message "unknown hostnamectl command: $words[1]" fi diff --git a/shell-completion/zsh/_localectl b/shell-completion/zsh/_localectl index 87432da..d8af4d1 100644 --- a/shell-completion/zsh/_localectl +++ b/shell-completion/zsh/_localectl @@ -22,8 +22,8 @@ _localectl_set-locale() { _localectl_set-keymap() { local -a _keymaps - _keymaps=( ${(f)"$(_call_program locales "$service" list-keymaps)"} ) if (( CURRENT <= 3 )); then + _keymaps=( ${(f)"$(_call_program locales "$service" list-keymaps)"} ) _describe keymaps _keymaps else _message "no more options" @@ -77,7 +77,7 @@ _localectl_command() { if (( $+functions[_localectl_$cmd] )); then _localectl_$cmd else - _message "no more options" + _message "unknown localectl command: $words[1]" fi fi } diff --git a/shell-completion/zsh/_systemctl b/shell-completion/zsh/_systemctl deleted file mode 100644 index b6cf664..0000000 --- a/shell-completion/zsh/_systemctl +++ /dev/null @@ -1,341 +0,0 @@ -#compdef systemctl - -(( $+functions[_systemctl_command] )) || _systemctl_command() -{ - local -a _systemctl_cmds - _systemctl_cmds=( - "list-sockets:List sockets" - "list-timers:List timers" - "list-units:List units" - "start:Start (activate) one or more units" - "stop:Stop (deactivate) one or more units" - "reload:Reload one or more units" - "restart:Start or restart one or more units" - "condrestart:Restart one or more units if active" - "try-restart:Restart one or more units if active" - "reload-or-restart:Reload one or more units if possible, otherwise start or restart" - "force-reload:Reload one or more units if possible, otherwise restart if active" - "hibernate:Hibernate the system" - "hybrid-sleep:Hibernate and suspend the system" - "reload-or-try-restart:Reload one or more units if possible, otherwise restart if active" - "isolate:Start one unit and stop all others" - "kill:Send signal to processes of a unit" - "is-active:Check whether units are active" - "is-failed:Check whether units are failed" - "status:Show runtime status of one or more units" - "show:Show properties of one or more units/jobs or the manager" - "cat:Show the source unit files and drop-ins" - "reset-failed:Reset failed state for all, one, or more units" - "list-unit-files:List installed unit files" - "enable:Enable one or more unit files" - "disable:Disable one or more unit files" - "reenable:Reenable one or more unit files" - "preset:Enable/disable one or more unit files based on preset configuration" - "help:Show documentation for specified units" - "list-dependencies:Show unit dependency tree" - "mask:Mask one or more units" - "unmask:Unmask one or more units" - "link:Link one or more units files into the search path" - "is-enabled:Check whether unit files are enabled" - "list-jobs:List jobs" - "cancel:Cancel all, one, or more jobs" - "snapshot:Create a snapshot" - "delete:Remove one or more snapshots" - "show-environment:Dump environment" - "set-environment:Set one or more environment variables" - "unset-environment:Unset one or more environment variables" - "daemon-reload:Reload systemd manager configuration" - "daemon-reexec:Reexecute systemd manager" - "default:Enter system default mode" - "rescue:Enter system rescue mode" - "emergency:Enter system emergency mode" - "halt:Shut down and halt the system" - "suspend:Suspend the system" - "poweroff:Shut down and power-off the system" - "reboot:Shut down and reboot the system" - "kexec:Shut down and reboot the system with kexec" - "exit:Ask for user instance termination" - ) - - if (( CURRENT == 1 )); then - _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@" - else - local curcontext="$curcontext" - - cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}" - # Deal with any aliases - case $cmd in - condrestart) cmd="try-restart";; - force-reload) cmd="reload-or-try-restart";; - esac - - if (( $#cmd )); then - curcontext="${curcontext%:*:*}:systemctl-${cmd}:" - - local update_policy - zstyle -s ":completion:${curcontext}:" cache-policy update_policy - if [[ -z "$update_policy" ]]; then - zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy - fi - - _call_function ret _systemctl_$cmd || _message 'no more arguments' - else - _message "unknown systemctl command: $words[1]" - fi - return ret - fi -} - -__systemctl() -{ - local -a _modes - _modes=("--user" "--system") - systemctl ${words:*_modes} --full --no-legend --no-pager "$@" -} - - -# Fills the unit list -_systemctl_all_units() -{ - if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) && - ! _retrieve_cache SYS_ALL_UNITS; - then - _sys_all_units=( $(__systemctl list-units --all | { while read a b; do echo " $a"; done; }) ) - _store_cache SYS_ALL_UNITS _sys_all_units - fi -} - -# Fills the unit list including all file units -_systemctl_really_all_units() -{ - local -a all_unit_files; - local -a really_all_units; - if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS ) && - ! _retrieve_cache SYS_REALLY_ALL_UNITS; - then - all_unit_files=( $(__systemctl list-unit-files | { while read a b; do echo " $a"; done; }) ) - _systemctl_all_units - really_all_units=($_sys_all_units $all_unit_files) - _sys_really_all_units=(${(u)really_all_units}) - _store_cache SYS_REALLY_ALL_UNITS _sys_really_all_units - fi -} - -_filter_units_by_property() { - local property=$1 value=$2 ; shift ; shift - local -a units ; units=($*) - local prop unit - for ((i=1; $i <= ${#units[*]}; i++)); do - # FIXME: "Failed to issue method call: Unknown unit" errors are ignored for - # now (related to DBUS_ERROR_UNKNOWN_OBJECT). in the future, we need to - # revert to calling 'systemctl show' once for all units, which is way - # faster - unit=${units[i]} - prop=${(f)"$(_call_program units "$service show --no-pager --property="$property" ${unit} 2>/dev/null")"} - if [[ "${prop}" = "$property=$value" ]]; then - echo " ${unit}" - fi - done -} - -_systemctl_active_units() {_sys_active_units=( $(__systemctl list-units | { while read a b; do echo " $a"; done; }) )} -_systemctl_inactive_units(){_sys_inactive_units=($(__systemctl list-units --all | { while read a b c d; do [[ $c == "inactive" || $c == "failed" ]] && echo " $a"; done; }) )} -_systemctl_failed_units() {_sys_failed_units=( $(__systemctl list-units --failed | { while read a b; do echo " $a"; done; }) )} -_systemctl_enabled_units() {_sys_enabled_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "enabled" ]] && echo " $a"; done; }) )} -_systemctl_disabled_units(){_sys_disabled_units=($(__systemctl list-unit-files | { while read a b; do [[ $b == "disabled" ]] && echo " $a"; done; }) )} -_systemctl_masked_units() {_sys_masked_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "masked" ]] && echo " $a"; done; }) )} - -# Completion functions for ALL_UNITS -for fun in is-active is-failed is-enabled status show cat mask preset help list-dependencies ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_really_all_units - compadd "$@" -a - _sys_really_all_units - } -done - -# Completion functions for ENABLED_UNITS -for fun in disable reenable ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_enabled_units - _systemctl_disabled_units - compadd "$@" -a - _sys_enabled_units _sys_disabled_units - } -done - -# Completion functions for DISABLED_UNITS -(( $+functions[_systemctl_enable] )) || _systemctl_enable() -{ - _systemctl_disabled_units - compadd "$@" -a - _sys_disabled_units -} - -# Completion functions for FAILED_UNITS -(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed() -{ - _systemctl_failed_units - compadd "$@" -a - _sys_failed_units || _message "no failed unit found" -} - -# Completion functions for STARTABLE_UNITS -(( $+functions[_systemctl_start] )) || _systemctl_start() -{ - _systemctl_inactive_units - compadd "$@" -a - _sys_inactive_units -} - -# Completion functions for STOPPABLE_UNITS -for fun in stop kill try-restart condrestart ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_active_units - compadd "$@" - $( _filter_units_by_property CanStop yes \ - ${_sys_active_units[*]} ) - } -done - -# Completion functions for ISOLATABLE_UNITS -(( $+functions[_systemctl_isolate] )) || _systemctl_isolate() -{ - _systemctl_all_units - compadd "$@" - $( _filter_units_by_property AllowIsolate yes \ - ${_sys_all_units[*]} ) -} - -# Completion functions for RELOADABLE_UNITS -for fun in reload reload-or-try-restart force-reload ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_active_units - compadd "$@" - $( _filter_units_by_property CanReload yes \ - ${_sys_active_units[*]} ) - } -done - -# Completion functions for RESTARTABLE_UNITS -for fun in restart reload-or-restart ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_all_units - compadd "$@" - $( _filter_units_by_property CanStart yes \ - ${_sys_all_units[*]} | while read line; do \ - [[ "$line" =~ \.device$ ]] || echo " $line"; \ - done ) - } -done - -# Completion functions for MASKED_UNITS -(( $+functions[_systemctl_unmask] )) || _systemctl_unmask() -{ - _systemctl_masked_units - compadd "$@" -a - _sys_masked_units || _message "no masked unit found" -} - -# Completion functions for JOBS -(( $+functions[_systemctl_cancel] )) || _systemctl_cancel() -{ - compadd "$@" - $(__systemctl list-jobs \ - | cut -d' ' -f1 2>/dev/null ) || _message "no job found" -} - -# Completion functions for SNAPSHOTS -(( $+functions[_systemctl_delete] )) || _systemctl_delete() -{ - compadd "$@" - $(__systemctl list-units --type snapshot --all \ - | cut -d' ' -f1 2>/dev/null ) || _message "no snapshot found" -} - -# Completion functions for ENVS -for fun in set-environment unset-environment ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - local fun=$0 ; fun=${fun##_systemctl_} - local suf - if [[ "${fun}" = "set-environment" ]]; then - suf='-S=' - fi - - compadd "$@" ${suf} - $(systemctl show-environment \ - | while read line; do echo " ${line%%\=}";done ) - } -done - -(( $+functions[_systemctl_link] )) || _systemctl_link() { _files } - -# no systemctl completion for: -# [STANDALONE]='daemon-reexec daemon-reload default -# emergency exit halt kexec list-jobs list-units -# list-unit-files poweroff reboot rescue show-environment' -# [NAME]='snapshot' - -_systemctl_caching_policy() -{ - local _sysunits - local -a oldcache - - # rebuild if cache is more than a day old - oldcache=( "$1"(mh+1) ) - (( $#oldcache )) && return 0 - - _sysunits=($(__systemctl --all | cut -d' ' -f1)) - - if (( $#_sysunits )); then - for unit in $_sysunits; do - [[ "$unit" -nt "$1" ]] && return 0 - done - fi - - return 1 -} - -_unit_states() { - local -a _states - _states=(loaded failed active inactive not-found listening running waiting plugged mounted exited dead masked) - _values -s , "${_states[@]}" -} - -_unit_types() { - local -a _types - _types=(automount device mount path service snapshot socket swap target timer) - _values -s , "${_types[@]}" -} - -_arguments -s \ - {-h,--help}'[Show help]' \ - '--version[Show package version]' \ - {-t+,--type=}'[List only units of a particular type]:unit type:_unit_types' \ - '--state=[Display units in the specifyied state]:unit state:_unit_states' \ - \*{-p+,--property=}'[Show only properties by specific name]:unit property' \ - {-a,--all}'[Show all units/properties, including dead/empty ones]' \ - '--reverse[Show reverse dependencies]' \ - '--after[Show units ordered after]' \ - '--before[Show units ordered before]' \ - '--failed[Show only failed units]' \ - {-l,--full}"[Don't ellipsize unit names on output]" \ - '--fail[When queueing a new job, fail if conflicting jobs are pending]' \ - '--show-types[When showing sockets, show socket type]' \ - '--irreversible[Mark transactions as irreversible]' \ - '--ignore-dependencies[When queueing a new job, ignore all its dependencies]' \ - {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \ - {-q,--quiet}'[Suppress output]' \ - '--no-block[Do not wait until operation finished]' \ - '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \ - '--no-pager[Do not pipe output into a pager]' \ - '--system[Connect to system manager]' \ - '--user[Connect to user service manager]' \ - "--no-wall[Don't send wall message before halt/power-off/reboot]" \ - '--global[Enable/disable unit files globally]' \ - "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \ - '--no-ask-password[Do not ask for system passwords]' \ - '--kill-who=[Who to send signal to]:killwho:(main control all)' \ - {-s+,--signal=}'[Which signal to send]:signal:_signals' \ - {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \ - '--root=[Enable unit files in the specified root directory]:directory:_directories' \ - '--runtime[Enable unit files only temporarily until next reboot]' \ - {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ - {-P,--privileged}'[Acquire privileges before execution]' \ - {-n+,--lines=}'[Journal entries to show]:number of entries' \ - {-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \ - '--plain[When used with list-dependencies, print output as a list]' \ - '*::systemctl command:_systemctl_command' diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in new file mode 100644 index 0000000..d9b8d1c --- /dev/null +++ b/shell-completion/zsh/_systemctl.in @@ -0,0 +1,354 @@ +#compdef systemctl + +(( $+functions[_systemctl_command] )) || _systemctl_command() +{ + local -a _systemctl_cmds + _systemctl_cmds=( + "list-sockets:List sockets" + "list-timers:List timers" + "list-units:List units" + "start:Start (activate) one or more units" + "stop:Stop (deactivate) one or more units" + "reload:Reload one or more units" + "restart:Start or restart one or more units" + "condrestart:Restart one or more units if active" + "try-restart:Restart one or more units if active" + "reload-or-restart:Reload one or more units if possible, otherwise start or restart" + "force-reload:Reload one or more units if possible, otherwise restart if active" + "hibernate:Hibernate the system" + "hybrid-sleep:Hibernate and suspend the system" + "reload-or-try-restart:Reload one or more units if possible, otherwise restart if active" + "isolate:Start one unit and stop all others" + "kill:Send signal to processes of a unit" + "is-active:Check whether units are active" + "is-failed:Check whether units are failed" + "status:Show runtime status of one or more units" + "show:Show properties of one or more units/jobs or the manager" + "cat:Show the source unit files and drop-ins" + "reset-failed:Reset failed state for all, one, or more units" + "list-unit-files:List installed unit files" + "enable:Enable one or more unit files" + "disable:Disable one or more unit files" + "reenable:Reenable one or more unit files" + "preset:Enable/disable one or more unit files based on preset configuration" + "help:Show documentation for specified units" + "list-dependencies:Show unit dependency tree" + "mask:Mask one or more units" + "unmask:Unmask one or more units" + "link:Link one or more units files into the search path" + "is-enabled:Check whether unit files are enabled" + "list-jobs:List jobs" + "cancel:Cancel all, one, or more jobs" + "snapshot:Create a snapshot" + "delete:Remove one or more snapshots" + "show-environment:Dump environment" + "set-environment:Set one or more environment variables" + "unset-environment:Unset one or more environment variables" + "daemon-reload:Reload systemd manager configuration" + "daemon-reexec:Reexecute systemd manager" + "default:Enter system default mode" + "rescue:Enter system rescue mode" + "emergency:Enter system emergency mode" + "halt:Shut down and halt the system" + "suspend:Suspend the system" + "poweroff:Shut down and power-off the system" + "reboot:Shut down and reboot the system" + "kexec:Shut down and reboot the system with kexec" + "exit:Ask for user instance termination" + ) + + if (( CURRENT == 1 )); then + _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@" + else + local curcontext="$curcontext" + + cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}" + # Deal with any aliases + case $cmd in + condrestart) cmd="try-restart";; + force-reload) cmd="reload-or-try-restart";; + esac + + if (( $#cmd )); then + curcontext="${curcontext%:*:*}:systemctl-${cmd}:" + + local update_policy + zstyle -s ":completion:${curcontext}:" cache-policy update_policy + if [[ -z "$update_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy + fi + + _call_function ret _systemctl_$cmd || _message 'no more arguments' + else + _message "unknown systemctl command: $words[1]" + fi + return ret + fi +} + +__systemctl() +{ + local -a _modes + _modes=("--user" "--system") + systemctl ${words:*_modes} --full --no-legend --no-pager "$@" +} + + +# Fills the unit list +_systemctl_all_units() +{ + if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) && + ! _retrieve_cache SYS_ALL_UNITS; + then + _sys_all_units=( $(__systemctl list-units --all | { while read a b; do echo " $a"; done; }) ) + _store_cache SYS_ALL_UNITS _sys_all_units + fi +} + +# Fills the unit list including all file units +_systemctl_really_all_units() +{ + local -a all_unit_files; + local -a really_all_units; + if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS ) && + ! _retrieve_cache SYS_REALLY_ALL_UNITS; + then + all_unit_files=( $(__systemctl list-unit-files | { while read a b; do echo " $a"; done; }) ) + _systemctl_all_units + really_all_units=($_sys_all_units $all_unit_files) + _sys_really_all_units=(${(u)really_all_units}) + _store_cache SYS_REALLY_ALL_UNITS _sys_really_all_units + fi +} + +_filter_units_by_property() { + local property=$1 value=$2 ; shift ; shift + local -a units ; units=($*) + local prop unit + for ((i=1; $i <= ${#units[*]}; i++)); do + # FIXME: "Failed to issue method call: Unknown unit" errors are ignored for + # now (related to DBUS_ERROR_UNKNOWN_OBJECT). in the future, we need to + # revert to calling 'systemctl show' once for all units, which is way + # faster + unit=${units[i]} + prop=${(f)"$(_call_program units "$service show --no-pager --property="$property" ${unit} 2>/dev/null")"} + if [[ "${prop}" = "$property=$value" ]]; then + echo " ${unit}" + fi + done +} + +_systemctl_active_units() {_sys_active_units=( $(__systemctl list-units | { while read a b; do echo " $a"; done; }) )} +_systemctl_inactive_units(){_sys_inactive_units=($(__systemctl list-units --all | { while read a b c d; do [[ $c == "inactive" || $c == "failed" ]] && echo " $a"; done; }) )} +_systemctl_failed_units() {_sys_failed_units=( $(__systemctl list-units --failed | { while read a b; do echo " $a"; done; }) )} +_systemctl_enabled_units() {_sys_enabled_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "enabled" ]] && echo " $a"; done; }) )} +_systemctl_disabled_units(){_sys_disabled_units=($(__systemctl list-unit-files | { while read a b; do [[ $b == "disabled" ]] && echo " $a"; done; }) )} +_systemctl_masked_units() {_sys_masked_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "masked" ]] && echo " $a"; done; }) )} + +# Completion functions for ALL_UNITS +for fun in is-active is-failed is-enabled status show cat mask preset help list-dependencies ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_really_all_units + compadd "$@" -a - _sys_really_all_units + } +done + +# Completion functions for ENABLED_UNITS +for fun in disable reenable ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_enabled_units + _systemctl_disabled_units + compadd "$@" -a - _sys_enabled_units _sys_disabled_units + } +done + +# Completion functions for DISABLED_UNITS +(( $+functions[_systemctl_enable] )) || _systemctl_enable() +{ + _systemctl_disabled_units + compadd "$@" -a - _sys_disabled_units +} + +# Completion functions for FAILED_UNITS +(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed() +{ + _systemctl_failed_units + compadd "$@" -a - _sys_failed_units || _message "no failed unit found" +} + +# Completion functions for STARTABLE_UNITS +(( $+functions[_systemctl_start] )) || _systemctl_start() +{ + _systemctl_inactive_units + compadd "$@" -a - _sys_inactive_units +} + +# Completion functions for STOPPABLE_UNITS +for fun in stop kill try-restart condrestart ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_active_units + compadd "$@" - $( _filter_units_by_property CanStop yes \ + ${_sys_active_units[*]} ) + } +done + +# Completion functions for ISOLATABLE_UNITS +(( $+functions[_systemctl_isolate] )) || _systemctl_isolate() +{ + _systemctl_all_units + compadd "$@" - $( _filter_units_by_property AllowIsolate yes \ + ${_sys_all_units[*]} ) +} + +# Completion functions for RELOADABLE_UNITS +for fun in reload reload-or-try-restart force-reload ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_active_units + compadd "$@" - $( _filter_units_by_property CanReload yes \ + ${_sys_active_units[*]} ) + } +done + +# Completion functions for RESTARTABLE_UNITS +for fun in restart reload-or-restart ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_all_units + compadd "$@" - $( _filter_units_by_property CanStart yes \ + ${_sys_all_units[*]} | while read line; do \ + [[ "$line" =~ \.device$ ]] || echo " $line"; \ + done ) + } +done + +# Completion functions for MASKED_UNITS +(( $+functions[_systemctl_unmask] )) || _systemctl_unmask() +{ + _systemctl_masked_units + compadd "$@" -a - _sys_masked_units || _message "no masked unit found" +} + +# Completion functions for JOBS +(( $+functions[_systemctl_cancel] )) || _systemctl_cancel() +{ + compadd "$@" - $(__systemctl list-jobs \ + | cut -d' ' -f1 2>/dev/null ) || _message "no job found" +} + +# Completion functions for SNAPSHOTS +(( $+functions[_systemctl_delete] )) || _systemctl_delete() +{ + compadd "$@" - $(__systemctl list-units --type snapshot --all \ + | cut -d' ' -f1 2>/dev/null ) || _message "no snapshot found" +} + +# Completion functions for ENVS +for fun in set-environment unset-environment ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local fun=$0 ; fun=${fun##_systemctl_} + local suf + if [[ "${fun}" = "set-environment" ]]; then + suf='-S=' + fi + + compadd "$@" ${suf} - $(systemctl show-environment \ + | while read line; do echo " ${line%%\=}";done ) + } +done + +(( $+functions[_systemctl_link] )) || _systemctl_link() { _files } + +# no systemctl completion for: +# [STANDALONE]='daemon-reexec daemon-reload default +# emergency exit halt kexec list-jobs list-units +# list-unit-files poweroff reboot rescue show-environment' +# [NAME]='snapshot' + +_systemctl_caching_policy() +{ + local _sysunits + local -a oldcache + + # rebuild if cache is more than a day old + oldcache=( "$1"(mh+1) ) + (( $#oldcache )) && return 0 + + _sysunits=($(__systemctl --all | cut -d' ' -f1)) + + if (( $#_sysunits )); then + for unit in $_sysunits; do + [[ "$unit" -nt "$1" ]] && return 0 + done + fi + + return 1 +} + +_unit_states() { + local -a _states + _states=(loaded failed active inactive not-found listening running waiting plugged mounted exited dead masked) + _values -s , "${_states[@]}" +} + +_unit_types() { + local -a _types + _types=(automount device mount path service snapshot socket swap target timer) + _values -s , "${_types[@]}" +} + +_unit_properties() { + if ( [[ ${+_sys_all_properties} -eq 0 ]] || _cache_invalid SYS_ALL_PROPERTIES ) && + ! _retrieve_cache SYS_ALL_PROPERTIES; + then + _sys_all_properties=( $( {__systemctl show --all; + @rootlibexecdir@/systemd --dump-configuration-items; } | { + while IFS='=' read -r a b; do [ -n "$b" ] && echo "$a"; done + }) ) + _store_cache SYS_ALL_PROPRTIES _sys_all_properties + fi + _values -s , "${_sys_all_properties[@]}" +} + +_arguments -s \ + {-h,--help}'[Show help]' \ + '--version[Show package version]' \ + {-t+,--type=}'[List only units of a particular type]:unit type:_unit_types' \ + '--state=[Display units in the specifyied state]:unit state:_unit_states' \ + {-p+,--property=}'[Show only properties by specific name]:unit property:_unit_properties' \ + {-a,--all}'[Show all units/properties, including dead/empty ones]' \ + '--reverse[Show reverse dependencies]' \ + '--after[Show units ordered after]' \ + '--before[Show units ordered before]' \ + '--failed[Show only failed units]' \ + {-l,--full}"[Don't ellipsize unit names on output]" \ + '--fail[When queueing a new job, fail if conflicting jobs are pending]' \ + '--show-types[When showing sockets, show socket type]' \ + '--irreversible[Mark transactions as irreversible]' \ + '--ignore-dependencies[When queueing a new job, ignore all its dependencies]' \ + {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \ + {-q,--quiet}'[Suppress output]' \ + '--no-block[Do not wait until operation finished]' \ + '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--system[Connect to system manager]' \ + '--user[Connect to user service manager]' \ + "--no-wall[Don't send wall message before halt/power-off/reboot]" \ + '--global[Enable/disable unit files globally]' \ + "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \ + '--no-ask-password[Do not ask for system passwords]' \ + '--kill-who=[Who to send signal to]:killwho:(main control all)' \ + {-s+,--signal=}'[Which signal to send]:signal:_signals' \ + {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \ + '--root=[Enable unit files in the specified root directory]:directory:_directories' \ + '--runtime[Enable unit files only temporarily until next reboot]' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-P,--privileged}'[Acquire privileges before execution]' \ + {-n+,--lines=}'[Journal entries to show]:number of entries' \ + {-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \ + '--plain[When used with list-dependencies, print output as a list]' \ + '*::systemctl command:_systemctl_command' diff --git a/src/core/main.c b/src/core/main.c index 38835fc..a732c69 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1543,7 +1543,15 @@ int main(int argc, char *argv[]) { if (in_initrd()) log_info("Running in initial RAM disk."); - empty_etc = dir_is_empty("/etc") > 0; + /* Let's check whether /etc is already populated. We + * don't actually really check for that, but use + * /etc/machine-id as flag file. This allows container + * managers and installers to provision a couple of + * files already. If the container manager wants to + * provision the machine ID itself it should pass + * $container_uuid to PID 1.*/ + + empty_etc = access("/etc/machine-id", F_OK) < 0; if (empty_etc) log_info("Running with unpopulated /etc."); } else { diff --git a/src/core/manager.c b/src/core/manager.c index 0cb2044..9b754d8 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -554,7 +554,7 @@ static int manager_setup_notify(Manager *m) { strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1); r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); if (r < 0) { - log_error("bind() failed: %m"); + log_error("bind(@%s) failed: %m", sa.un.sun_path+1); return -errno; } @@ -2539,7 +2539,8 @@ void manager_check_finished(Manager *m) { } SET_FOREACH(u, m->startup_units, i) - cgroup_context_apply(unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path, manager_state(m)); + if (u->cgroup_path) + cgroup_context_apply(unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path, manager_state(m)); bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec); diff --git a/src/core/path.c b/src/core/path.c index 20e454d..f54c77f 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -99,7 +99,8 @@ int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) { break; } - log_warning("Failed to add watch on %s: %m", s->path); + log_warning("Failed to add watch on %s: %s", s->path, + errno == ENOSPC ? "too many watches" : strerror(-r)); r = -errno; if (cut) *cut = tmp; diff --git a/src/core/service.c b/src/core/service.c index 0b19767..73a0e84 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1699,6 +1699,9 @@ static int service_start(Unit *u) { s->main_pid_alien = false; s->forbid_restart = false; + free(s->status_text); + s->status_text = NULL; + service_enter_start_pre(s); return 0; } @@ -2547,11 +2550,15 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata) { Service *s = SERVICE(userdata); + char t[FORMAT_TIMESPAN_MAX]; assert(s); assert(source == s->watchdog_event_source); - log_error_unit(UNIT(s)->id, "%s watchdog timeout!", UNIT(s)->id); + log_error_unit(UNIT(s)->id, + "%s watchdog timeout (limit %s)!", + UNIT(s)->id, + format_timespan(t, sizeof(t), s->watchdog_usec, 1)); service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_WATCHDOG); return 0; diff --git a/src/escape/Makefile b/src/escape/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/src/escape/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/src/escape/escape.c b/src/escape/escape.c new file mode 100644 index 0000000..ba2fb47 --- /dev/null +++ b/src/escape/escape.c @@ -0,0 +1,239 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2014 Michael Biebl + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "log.h" +#include "unit-name.h" +#include "build.h" +#include "strv.h" + +static enum { + ACTION_ESCAPE, + ACTION_UNESCAPE, + ACTION_MANGLE +} arg_action = ACTION_ESCAPE; +static const char *arg_suffix = NULL; +static const char *arg_template = NULL; +static bool arg_path = false; + +static int help(void) { + + printf("%s [OPTIONS...] [NAME...]\n\n" + "Show system and user paths.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --suffix=SUFFIX Unit suffix to append to escaped strings\n" + " --template=TEMPLATE Insert strings as instance into template\n" + " -u --unescape Unescape strings\n" + " -m --mangle Mangle strings\n" + " -p --path When escaping/unescaping assume the string is a path\n", + program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_SUFFIX, + ARG_TEMPLATE + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "suffix", required_argument, NULL, ARG_SUFFIX }, + { "template", required_argument, NULL, ARG_TEMPLATE }, + { "unescape", no_argument, NULL, 'u' }, + { "mangle", no_argument, NULL, 'm' }, + { "path", no_argument, NULL, 'p' }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0) { + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + puts(PACKAGE_STRING); + puts(SYSTEMD_FEATURES); + return 0; + + case ARG_SUFFIX: + + if (unit_type_from_string(optarg) < 0) { + log_error("Invalid unit suffix type %s.", optarg); + return -EINVAL; + } + + arg_suffix = optarg; + break; + + case ARG_TEMPLATE: + + if (!unit_name_is_valid(optarg, true) || !unit_name_is_template(optarg)) { + log_error("Template name %s is not valid.", optarg); + return -EINVAL; + } + + arg_template = optarg; + break; + + case 'u': + arg_action = ACTION_UNESCAPE; + break; + + case 'm': + arg_action = ACTION_MANGLE; + break; + + case 'p': + arg_path = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + } + + if (optind >= argc) { + log_error("Not enough arguments."); + return -EINVAL; + } + + if (arg_template && arg_suffix) { + log_error("--suffix= and --template= may not be combined."); + return -EINVAL; + } + + if ((arg_template || arg_suffix) && arg_action != ACTION_ESCAPE) { + log_error("--suffix= and --template= are not compatible with --unescape or --mangle."); + return -EINVAL; + } + + if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE)) { + log_error("--path may not be combined with --mangle."); + return -EINVAL; + } + + return 1; +} + +int main(int argc, char *argv[]) { + char **i; + int r; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + STRV_FOREACH(i, argv + optind) { + _cleanup_free_ char *e = NULL; + + switch (arg_action) { + + case ACTION_ESCAPE: + if (arg_path) + e = unit_name_path_escape(*i); + else + e = unit_name_escape(*i); + + if (!e) { + r = log_oom(); + goto finish; + } + + if (arg_template) { + char *x; + + x = unit_name_replace_instance(arg_template, e); + if (!x) { + r = log_oom(); + goto finish; + } + + free(e); + e = x; + } else if (arg_suffix) { + char *x; + + x = strjoin(e, ".", arg_suffix, NULL); + if (!x) { + r = log_oom(); + goto finish; + } + + free(e); + e = x; + } + + break; + + case ACTION_UNESCAPE: + if (arg_path) + e = unit_name_path_unescape(*i); + else + e = unit_name_unescape(*i); + + if (!e) { + r = log_oom(); + goto finish; + } + break; + + case ACTION_MANGLE: + e = unit_name_mangle(*i, MANGLE_NOGLOB); + if (!e) { + r = log_oom(); + goto finish; + } + break; + } + + if (i != argv+optind) + fputc(' ', stdout); + + fputs(e, stdout); + } + + fputc('\n', stdout); + +finish: + return r <= 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 14629dd..eaae113 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -144,7 +144,8 @@ static bool valid_chassis(const char *chassis) { "laptop\0" "server\0" "tablet\0" - "handset\0", + "handset\0" + "watch\0", chassis); } @@ -550,8 +551,7 @@ static int set_machine_info(Context *c, sd_bus *bus, sd_bus_message *m, int prop if (prop == PROP_ICON_NAME && !filename_is_safe(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name); - if (prop == PROP_PRETTY_HOSTNAME && - (string_has_cc(name) || chars_intersect(name, "\t"))) + if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name); if (prop == PROP_CHASSIS && !valid_chassis(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name); diff --git a/src/journal/compress.c b/src/journal/compress.c index 1fc62ea..9c0b74c 100644 --- a/src/journal/compress.c +++ b/src/journal/compress.c @@ -30,6 +30,13 @@ #include "util.h" bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size) { + static const lzma_options_lzma opt = { + 1u << 20u, NULL, 0, LZMA_LC_DEFAULT, LZMA_LP_DEFAULT, + LZMA_PB_DEFAULT, LZMA_MODE_FAST, 128, LZMA_MF_HC3, 4}; + static const lzma_filter filters[2] = { + {LZMA_FILTER_LZMA2, (lzma_options_lzma*) &opt}, + {LZMA_VLI_UNKNOWN, NULL} + }; lzma_ret ret; size_t out_pos = 0; @@ -41,8 +48,11 @@ bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_ /* Returns false if we couldn't compress the data or the * compressed result is longer than the original */ - ret = lzma_easy_buffer_encode(LZMA_PRESET_DEFAULT, LZMA_CHECK_NONE, NULL, - src, src_size, dst, &out_pos, src_size); + if (src_size < 80) + return -ENOBUFS; + + ret = lzma_stream_buffer_encode((lzma_filter*) filters, LZMA_CHECK_NONE, NULL, + src, src_size, dst, &out_pos, src_size - 1); if (ret != LZMA_OK) return false; diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index 2158d73..ecde547 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -595,7 +595,8 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { retrieve(data, len, "COREDUMP_FILENAME", &filename); if (filename && access(filename, R_OK) < 0) { - log_debug("File %s is not readable: %m", filename); + log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, + "File %s is not readable: %m", filename); free(filename); filename = NULL; } @@ -668,7 +669,7 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { #endif } else { if (r == -ENOENT) - log_error("Coredump neither in journal file nor stored externally on disk."); + log_error("Cannot retrieve coredump from journal nor disk."); else log_error("Failed to retrieve COREDUMP field: %s", strerror(-r)); goto error; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index b3b1ffc..ef54af4 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -271,12 +271,6 @@ static int journal_file_verify_header(JournalFile *f) { !VALID64(le64toh(f->header->entry_array_offset))) return -ENODATA; - if (le64toh(f->header->data_hash_table_offset) < le64toh(f->header->header_size) || - le64toh(f->header->field_hash_table_offset) < le64toh(f->header->header_size) || - le64toh(f->header->tail_object_offset) < le64toh(f->header->header_size) || - le64toh(f->header->entry_array_offset) < le64toh(f->header->header_size)) - return -ENODATA; - if (f->writable) { uint8_t state; sd_id128_t machine_id; diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index c54f647..666cbd2 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -387,7 +387,7 @@ int server_open_native_socket(Server*s) { r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); if (r < 0) { - log_error("bind() failed: %m"); + log_error("bind(%s) failed: %m", sa.un.sun_path); return -errno; } diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index 89da150..8a983d8 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -450,14 +450,14 @@ int server_open_stdout_socket(Server *s) { r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); if (r < 0) { - log_error("bind() failed: %m"); + log_error("bind(%s) failed: %m", sa.un.sun_path); return -errno; } chmod(sa.un.sun_path, 0666); if (listen(s->stdout_fd, SOMAXCONN) < 0) { - log_error("listen() failed: %m"); + log_error("listen(%s) failed: %m", sa.un.sun_path); return -errno; } } else diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index b826e23..f97e0d2 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -441,7 +441,7 @@ int server_open_syslog_socket(Server *s) { r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); if (r < 0) { - log_error("bind() failed: %m"); + log_error("bind(%s) failed: %m", sa.un.sun_path); return -errno; } diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index ca805f8..15dae90 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -2390,7 +2390,7 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) { Iterator i; JournalFile *f; - bool first = true; + bool found = false; int r; assert_return(j, -EINVAL); @@ -2409,21 +2409,21 @@ _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot if (r == 0) continue; - if (first) { + if (found) { if (from) - *from = fr; + *from = MIN(fr, *from); if (to) - *to = t; - first = false; + *to = MAX(t, *to); } else { if (from) - *from = MIN(fr, *from); + *from = fr; if (to) - *to = MAX(t, *to); + *to = t; + found = true; } } - return first ? 0 : 1; + return found; } void journal_print_header(sd_journal *j) { diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c index 3e986ed..45eb327 100644 --- a/src/journal/test-journal-send.c +++ b/src/journal/test-journal-send.c @@ -72,7 +72,7 @@ int main(int argc, char *argv[]) { "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN), NULL); - sleep(10); + sleep(1); return 0; } diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 8fdbbfe..a83778e 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -708,7 +708,8 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, return 0; } - dhcp6_lease_clear_timers(&client->lease->ia); + if (client->lease) + dhcp6_lease_clear_timers(&client->lease->ia); client->lease = sd_dhcp6_lease_unref(client->lease); client->lease = lease; diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c index 7ade915..360c854 100644 --- a/src/libsystemd/sd-path/sd-path.c +++ b/src/libsystemd/sd-path/sd-path.c @@ -22,6 +22,7 @@ #include "path-util.h" #include "strv.h" #include "sd-path.h" +#include "missing.h" static int from_environment(const char *envname, const char *fallback, const char **ret) { assert(ret); diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules index e1cf897..694df2c 100644 --- a/src/login/70-uaccess.rules +++ b/src/login/70-uaccess.rules @@ -12,7 +12,7 @@ ENV{MAJOR}=="", GOTO="uaccess_end" SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess" # Digicams with proprietary protocol -ENV{ID_GPHOTO2}=="*?", TAG+="uaccess" +ENV{ID_GPHOTO2}=="?*", TAG+="uaccess" # SCSI and USB scanners ENV{libsane_matched}=="yes", TAG+="uaccess" @@ -49,13 +49,13 @@ SUBSYSTEM=="drm", KERNEL=="card*|renderD*", TAG+="uaccess" SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess" # smart-card readers -ENV{ID_SMARTCARD_READER}=="*?", TAG+="uaccess" +ENV{ID_SMARTCARD_READER}=="?*", TAG+="uaccess" # (USB) authentication devices -ENV{ID_SECURITY_TOKEN}=="*?", TAG+="uaccess" +ENV{ID_SECURITY_TOKEN}=="?*", TAG+="uaccess" # PDA devices -ENV{ID_PDA}=="*?", TAG+="uaccess" +ENV{ID_PDA}=="?*", TAG+="uaccess" # Programmable remote control ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess" @@ -64,12 +64,15 @@ ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess" SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess" # color measurement devices -ENV{COLOR_MEASUREMENT_DEVICE}=="*?", TAG+="uaccess" +ENV{COLOR_MEASUREMENT_DEVICE}=="?*", TAG+="uaccess" # DDC/CI device, usually high-end monitors such as the DreamColor -ENV{DDC_DEVICE}=="*?", TAG+="uaccess" +ENV{DDC_DEVICE}=="?*", TAG+="uaccess" # media player raw devices (for user-mode drivers, Android SDK, etc.) SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess" +# software-defined radio communication devices +ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess" + LABEL="uaccess_end" diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c index 4bbeb64..af7c352 100644 --- a/src/login/logind-acl.c +++ b/src/login/logind-acl.c @@ -277,7 +277,10 @@ int devnode_acl_all(struct udev *udev, SET_FOREACH(n, nodes, i) { int k; - log_debug("Fixing up ACLs at %s for seat %s", n, seat); + log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"→"UID_FMT"%s%s)", + n, seat, old_uid, new_uid, + del ? " del" : "", add ? " add" : ""); + k = devnode_acl(n, flush, del, old_uid, add, new_uid); if (k == -ENOENT) log_debug("Device %s disappeared while setting ACLs", n); diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 3114de8..9992195 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -275,8 +275,13 @@ int seat_switch_to(Seat *s, unsigned int num) { if (!num) return -EINVAL; - if (num >= s->position_count || !s->positions[num]) + if (num >= s->position_count || !s->positions[num]) { + /* allow switching to unused VTs to trigger auto-activate */ + if (seat_has_vts(s) && num < 64) + return chvt(num); + return -EINVAL; + } return session_activate(s->positions[num]); } diff --git a/src/machine/machine.c b/src/machine/machine.c index c0fa1b2..cf38e3f 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -371,7 +371,7 @@ static int machine_stop_scope(Machine *m) { free(m->scope_job); m->scope_job = job; - return r; + return 0; } int machine_stop(Machine *m) { diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 14c0417..6257372 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -599,10 +599,35 @@ static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) return 0; } +static int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { + _cleanup_link_unref_ Link *link = userdata; + int r; + + assert(rtnl); + assert(m); + assert(link); + assert(link->manager); + + for (; m; m = sd_rtnl_message_next(m)) { + r = sd_rtnl_message_get_errno(m); + if (r < 0) { + log_debug_link(link, "getting address failed: %s", strerror(-r)); + continue; + } + + r = link_rtnl_process_address(rtnl, m, link->manager); + if (r < 0) + log_warning_link(link, "could not process address: %s", strerror(-r)); + } + + return 1; +} + static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; + assert(rtnl); assert(m); assert(link); assert(link->ifname); @@ -623,6 +648,11 @@ static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { link->ifname, strerror(-r), "ERRNO=%d", -r, NULL); + if (r >= 0) { + /* calling handler directly so take a ref */ + link_ref(link); + link_get_address_handler(rtnl, m, link); + } if (link->addr_messages == 0) { log_debug_link(link, "addresses set"); @@ -2140,7 +2170,7 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use r = address_new_dynamic(&address); if (r < 0) - return 0; + return r; r = sd_rtnl_message_addr_get_family(message, &address->family); if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) { @@ -2204,7 +2234,10 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use case RTM_NEWADDR: if (!address_dropped) log_debug_link(link, "added address: %s/%u", buf, - address->prefixlen); + address->prefixlen); + else + log_debug_link(link, "updated address: %s/%u", buf, + address->prefixlen); LIST_PREPEND(addresses, link->addresses, address); address = NULL; @@ -2215,10 +2248,12 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use case RTM_DELADDR: if (address_dropped) { log_debug_link(link, "removed address: %s/%u", buf, - address->prefixlen); + address->prefixlen); link_save(link); - } + } else + log_warning_link(link, "removing non-existent address: %s/%u", + buf, address->prefixlen); break; default: @@ -2228,30 +2263,6 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use return 1; } -static int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(rtnl); - assert(m); - assert(link); - assert(link->manager); - - for (; m; m = sd_rtnl_message_next(m)) { - r = sd_rtnl_message_get_errno(m); - if (r < 0) { - log_debug_link(link, "getting address failed: %s", strerror(-r)); - continue; - } - - r = link_rtnl_process_address(rtnl, m, link->manager); - if (r < 0) - log_warning_link(link, "could not process address: %s", strerror(-r)); - } - - return 1; -} - int link_add(Manager *m, sd_rtnl_message *message, Link **ret) { Link *link; _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL; diff --git a/src/network/networkd-macvlan.c b/src/network/networkd-macvlan.c index 9227144..7c23426 100644 --- a/src/network/networkd-macvlan.c +++ b/src/network/networkd-macvlan.c @@ -150,6 +150,8 @@ int netdev_create_macvlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t return r; } + link_ref(link); + log_debug_netdev(netdev, "creating netdev"); netdev->state = NETDEV_STATE_CREATING; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 9ab4f23..9f6de18 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -92,7 +92,7 @@ static int network_load_one(Manager *manager, const char *filename) { network->dhcp_routes = true; network->dhcp_sendhost = true; - r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup, + r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCP\0DHCPv4\0", config_item_perf_lookup, (void*) network_network_gperf_lookup, false, false, network); if (r < 0) { log_warning("Could not parse config file %s: %s", filename, strerror(-r)); diff --git a/src/network/networkd-tunnel.c b/src/network/networkd-tunnel.c index 7341487..5a244f6 100644 --- a/src/network/networkd-tunnel.c +++ b/src/network/networkd-tunnel.c @@ -529,6 +529,8 @@ int netdev_create_tunnel(NetDev *netdev, Link *link, sd_rtnl_message_handler_t c return r; } + link_ref(link); + log_debug_netdev(netdev, "Creating tunnel netdev: %s", netdev_kind_to_string(netdev->kind)); diff --git a/src/network/networkd-vlan.c b/src/network/networkd-vlan.c index 1d812fd..8727b9f 100644 --- a/src/network/networkd-vlan.c +++ b/src/network/networkd-vlan.c @@ -139,6 +139,8 @@ int netdev_create_vlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cal return r; } + link_ref(link); + log_debug_netdev(netdev, "creating netdev"); netdev->state = NETDEV_STATE_CREATING; diff --git a/src/network/networkd-vxlan.c b/src/network/networkd-vxlan.c index 8832024..1604594 100644 --- a/src/network/networkd-vxlan.c +++ b/src/network/networkd-vxlan.c @@ -154,6 +154,8 @@ int netdev_create_vxlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t ca return r; } + link_ref(link); + log_debug_netdev(netdev, "Creating vxlan netdev: %s", netdev_kind_to_string(netdev->kind)); diff --git a/src/shared/architecture.c b/src/shared/architecture.c index 7dd049a..dc45f35 100644 --- a/src/shared/architecture.c +++ b/src/shared/architecture.c @@ -115,7 +115,6 @@ Architecture uname_architecture(void) { #elif defined(__tilegx__) { "tilegx", ARCHITECTURE_TILEGX }, #elif defined(__cris__) - { "cris", ARCHITECTURE_CRIS }, { "crisv32", ARCHITECTURE_CRIS }, #else #error "Please register your architecture here!" @@ -154,7 +153,9 @@ static const char *const architecture_table[_ARCHITECTURE_MAX] = { [ARCHITECTURE_SPARC] = "sparc", [ARCHITECTURE_SPARC64] = "sparc64", [ARCHITECTURE_MIPS] = "mips", + [ARCHITECTURE_MIPS_LE] = "mips-le", [ARCHITECTURE_MIPS64] = "mips64", + [ARCHITECTURE_MIPS64_LE] = "mips64-le", [ARCHITECTURE_ALPHA] = "alpha", [ARCHITECTURE_ARM] = "arm", [ARCHITECTURE_ARM_BE] = "arm-be", diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 5997a03..8d03f4a 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -270,7 +270,7 @@ static int create_socket(char **name) { if (r < 0) { r = -errno; - log_error("bind() failed: %m"); + log_error("bind(%s) failed: %m", sa.un.sun_path); goto fail; } diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c index daaeaca..addd26c 100644 --- a/src/shared/base-filesystem.c +++ b/src/shared/base-filesystem.c @@ -42,12 +42,13 @@ typedef struct BaseFilesystem { } BaseFilesystem; static const BaseFilesystem table[] = { - { "bin", 0, "usr/bin", NULL }, - { "lib", 0, "usr/lib", NULL }, - { "root", 0755, NULL, NULL }, - { "sbin", 0, "usr/sbin", NULL }, + { "bin", 0, "usr/bin\0", NULL }, + { "lib", 0, "usr/lib\0", NULL }, + { "root", 0755, NULL, NULL }, + { "sbin", 0, "usr/sbin\0", NULL }, #if defined(__i386__) || defined(__x86_64__) - { "lib64", 0, "usr/lib/x86_64-linux-gnu\0usr/lib64", "ld-linux-x86-64.so.2" }, + { "lib64", 0, "usr/lib/x86_64-linux-gnu\0" + "usr/lib64\0", "ld-linux-x86-64.so.2" }, #endif }; diff --git a/src/shared/dropin.h b/src/shared/dropin.h index 27a2b29..9c9742d 100644 --- a/src/shared/dropin.h +++ b/src/shared/dropin.h @@ -21,6 +21,8 @@ along with systemd; If not, see . ***/ +#include "macro.h" + int drop_in_file(const char *dir, const char *unit, unsigned level, const char *name, char **_p, char **_q); @@ -28,4 +30,4 @@ int write_drop_in(const char *dir, const char *unit, unsigned level, const char *name, const char *data); int write_drop_in_format(const char *dir, const char *unit, unsigned level, - const char *name, const char *format, ...); + const char *name, const char *format, ...) _printf_(5, 6); diff --git a/src/shared/env-util.c b/src/shared/env-util.c index b2e4553..20b208f 100644 --- a/src/shared/env-util.c +++ b/src/shared/env-util.c @@ -78,7 +78,9 @@ bool env_value_is_valid(const char *e) { if (!utf8_is_valid(e)) return false; - if (string_has_cc(e)) + /* bash allows tabs in environment variables, and so should + * we */ + if (string_has_cc(e, "\t")) return false; /* POSIX says the overall size of the environment block cannot diff --git a/src/shared/fileio-label.c b/src/shared/fileio-label.c index 0711826..c3def3c 100644 --- a/src/shared/fileio-label.c +++ b/src/shared/fileio-label.c @@ -25,12 +25,13 @@ #include "fileio-label.h" #include "label.h" +#include "util.h" int write_string_file_atomic_label(const char *fn, const char *line) { int r; r = label_context_set(fn, S_IFREG); - if (r < 0) + if (r < 0) return r; write_string_file_atomic(fn, line); @@ -44,7 +45,7 @@ int write_env_file_label(const char *fname, char **l) { int r; r = label_context_set(fname, S_IFREG); - if (r < 0) + if (r < 0) return r; write_env_file(fname, l); @@ -53,3 +54,18 @@ int write_env_file_label(const char *fname, char **l) { return r; } + +int fopen_temporary_label(const char *target, + const char *path, FILE **f, char **temp_path) { + int r; + + r = label_context_set(target, S_IFREG); + if (r < 0) + return r; + + r = fopen_temporary(path, f, temp_path); + + label_context_clear(); + + return r; +} diff --git a/src/shared/fileio-label.h b/src/shared/fileio-label.h index fce4fe0..25fa351 100644 --- a/src/shared/fileio-label.h +++ b/src/shared/fileio-label.h @@ -27,3 +27,5 @@ int write_string_file_atomic_label(const char *fn, const char *line); int write_env_file_label(const char *fname, char **l); +int fopen_temporary_label(const char *target, + const char *path, FILE **f, char **temp_path); diff --git a/src/shared/fileio.c b/src/shared/fileio.c index fb1c1bc..d22770b 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -738,11 +738,11 @@ static void write_env_var(FILE *f, const char *v) { p++; fwrite(v, 1, p-v, f); - if (string_has_cc(p) || chars_intersect(p, WHITESPACE "\'\"\\`$")) { + if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) { fputc('\"', f); for (; *p; p++) { - if (strchr("\'\"\\`$", *p)) + if (strchr(SHELL_NEED_ESCAPE, *p)) fputc('\\', f); fputc(*p, f); diff --git a/src/shared/generator.c b/src/shared/generator.c index 5d5b6a0..414470b 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -125,7 +125,7 @@ int generator_write_timeouts(const char *dir, const char *what, const char *wher char *prefix, *postfix; prefix = strndupa(opts, start - opts - (start != opts)); - postfix = timeout + len + (timeout[len] != '\0'); + postfix = timeout + len + (start == opts && timeout[len] != '\0'); *filtered = strjoin(prefix, *postfix ? postfix : NULL, NULL); if (!*filtered) return log_oom(); @@ -148,7 +148,7 @@ int generator_write_timeouts(const char *dir, const char *what, const char *wher return write_drop_in_format(dir, unit, 50, "device-timeout", "# Automatically generated by %s\n\n" - "[Unit]\nJobTimeoutSec=%u", + "[Unit]\nJobTimeoutSec=" USEC_FMT, program_invocation_short_name, u / USEC_PER_SEC); } diff --git a/src/shared/missing.h b/src/shared/missing.h index f129f0b..2985285 100644 --- a/src/shared/missing.h +++ b/src/shared/missing.h @@ -371,6 +371,27 @@ static inline int setns(int fd, int nstype) { #define LOOP_CTL_GET_FREE 0x4C82 #endif +#if !HAVE_DECL_IFLA_MACVLAN_FLAGS +#define IFLA_MACVLAN_UNSPEC 0 +#define IFLA_MACVLAN_MODE 1 +#define IFLA_MACVLAN_FLAGS 2 +#define __IFLA_MACVLAN_MAX 3 + +#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1) +#endif + +#if !HAVE_DECL_IFLA_VTI_REMOTE +#define IFLA_VTI_UNSPEC 0 +#define IFLA_VTI_LINK 1 +#define IFLA_VTI_IKEY 2 +#define IFLA_VTI_OKEY 3 +#define IFLA_VTI_LOCAL 4 +#define IFLA_VTI_REMOTE 5 +#define __IFLA_VTI_MAX 6 + +#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1) +#endif + #if !HAVE_DECL_IFLA_PHYS_PORT_ID #undef IFLA_PROMISCUITY #define IFLA_PROMISCUITY 30 diff --git a/src/shared/mkdir.h b/src/shared/mkdir.h index d15ede6..dd5b41e 100644 --- a/src/shared/mkdir.h +++ b/src/shared/mkdir.h @@ -22,6 +22,7 @@ along with systemd; If not, see . ***/ +#include #include int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index e0aaf44..7d53d85 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -125,26 +125,8 @@ static char** user_dirs( goto fail; } else if (home) { - _cleanup_free_ char *data_home_parent = NULL; - if (asprintf(&data_home, "%s/.local/share/systemd/user", home) < 0) goto fail; - - /* There is really no need for two unit dirs in $HOME, - * except to be fully compliant with the XDG spec. We - * now try to link the two dirs, so that we can - * minimize disk seeks a little. Further down we'll - * then filter out this link, if it is actually is - * one. */ - - if (path_get_parent(data_home, &data_home_parent) >= 0) { - _cleanup_free_ char *config_home_relative = NULL; - - if (path_make_relative(data_home_parent, config_home, &config_home_relative) >= 0) { - mkdir_parents_label(data_home, 0777); - (void) symlink(config_home_relative, data_home); - } - } } e = getenv("XDG_DATA_DIRS"); diff --git a/src/shared/util.c b/src/shared/util.c index 3d875c7..03a5860 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -1608,8 +1608,9 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { return -ETIMEDOUT; } + errno = 0; if (!fgets(line, sizeof(line), f)) - return -EIO; + return errno ? -errno : -EIO; truncate_nl(line); @@ -5349,13 +5350,14 @@ bool filename_is_safe(const char *p) { bool string_is_safe(const char *p) { const char *t; - assert(p); + if (!p) + return false; for (t = p; *t; t++) { if (*t > 0 && *t < ' ') return false; - if (strchr("\\\"\'", *t)) + if (strchr("\\\"\'\0x7f", *t)) return false; } @@ -5363,18 +5365,25 @@ bool string_is_safe(const char *p) { } /** - * Check if a string contains control characters. - * Spaces and tabs are not considered control characters. + * Check if a string contains control characters. If 'ok' is non-NULL + * it may be a string containing additional CCs to be considered OK. */ -bool string_has_cc(const char *p) { +bool string_has_cc(const char *p, const char *ok) { const char *t; assert(p); - for (t = p; *t; t++) - if (*t > 0 && *t < ' ' && *t != '\t') + for (t = p; *t; t++) { + if (ok && strchr(ok, *t)) + continue; + + if (*t > 0 && *t < ' ') return true; + if (*t == 127) + return true; + } + return false; } diff --git a/src/shared/util.h b/src/shared/util.h index e23069c..64b9fc6 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -93,6 +93,12 @@ #define COMMENTS "#;" #define GLOB_CHARS "*?[" +/* What characters are special in the shell? */ +/* must be escaped outside and inside double-quotes */ +#define SHELL_NEED_ESCAPE "\"\\`$" +/* can be escaped or double-quoted */ +#define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;" + #define FORMAT_BYTES_MAX 8 #define ANSI_HIGHLIGHT_ON "\x1B[1;39m" @@ -692,7 +698,7 @@ _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_ bool filename_is_safe(const char *p) _pure_; bool path_is_safe(const char *p) _pure_; bool string_is_safe(const char *p) _pure_; -bool string_has_cc(const char *p) _pure_; +bool string_has_cc(const char *p, const char *ok) _pure_; /** * Check if a string contains any glob patterns. diff --git a/src/shared/virt.c b/src/shared/virt.c index 774915f..b436895 100644 --- a/src/shared/virt.c +++ b/src/shared/virt.c @@ -173,7 +173,7 @@ int detect_vm(const char **id) { if (streq(cap, "control_d")) break; - if (!i) { + if (!cap) { _id = "xen"; r = 1; } @@ -220,6 +220,23 @@ int detect_vm(const char **id) { goto finish; } +#if defined(__s390__) + { + _cleanup_free_ char *t = NULL; + + r = get_status_field("/proc/sysinfo", "VM00 Control Program:", &t); + if (r >= 0) { + if (streq(t, "z/VM")) + _id = "zvm"; + else + _id = "kvm"; + r = 1; + + goto finish; + } + } +#endif + r = 0; finish: diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 03720f4..8086e1e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -456,7 +456,7 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { } if (circle_len > 0) - printf("%s%s%s", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle); + printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle); printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s", on_active, id_len, id, off_active, diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 1209a5a..2387d58 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "util.h" #include "hashmap.h" @@ -34,6 +35,8 @@ #include "conf-files.h" #include "copy.h" #include "utf8.h" +#include "label.h" +#include "fileio-label.h" typedef enum ItemType { ADD_USER = 'u', @@ -61,6 +64,8 @@ typedef struct Item { static char *arg_root = NULL; static const char conf_file_dirs[] = + "/etc/sysusers.d\0" + "/run/sysusers.d\0" "/usr/local/lib/sysusers.d\0" "/usr/lib/sysusers.d\0" #ifdef HAVE_SPLIT_USR @@ -190,8 +195,9 @@ static int load_group_database(void) { return 0; } -static int make_backup(const char *x) { - _cleanup_close_ int src = -1, dst = -1; +static int make_backup(const char *target, const char *x) { + _cleanup_close_ int src = -1; + _cleanup_fclose_ FILE *dst = NULL; char *backup, *temp; struct timespec ts[2]; struct stat st; @@ -208,30 +214,30 @@ static int make_backup(const char *x) { if (fstat(src, &st) < 0) return -errno; - temp = strappenda(x, ".XXXXXX"); - dst = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC|O_NOCTTY); - if (dst < 0) - return dst; + r = fopen_temporary_label(target, x, &dst, &temp); + if (r < 0) + return r; - r = copy_bytes(src, dst, (off_t) -1); + r = copy_bytes(src, fileno(dst), (off_t) -1); if (r < 0) goto fail; + /* Don't fail on chmod() or chown(). If it stays owned by us + * and/or unreadable by others, then it isn't too bad... */ + + backup = strappenda(x, "-"); + /* Copy over the access mask */ - if (fchmod(dst, st.st_mode & 07777) < 0) { - r = -errno; - goto fail; - } + if (fchmod(fileno(dst), st.st_mode & 07777) < 0) + log_warning("Failed to change mode on %s: %m", backup); - /* Don't fail on chmod(). If it stays owned by us, then it - * isn't too bad... */ - fchown(dst, st.st_uid, st.st_gid); + if (fchown(fileno(dst), st.st_uid, st.st_gid)< 0) + log_warning("Failed to change ownership of %s: %m", backup); ts[0] = st.st_atim; ts[1] = st.st_mtim; - futimens(dst, ts); + futimens(fileno(dst), ts); - backup = strappenda(x, "-"); if (rename(temp, backup) < 0) goto fail; @@ -309,7 +315,7 @@ static int write_files(void) { _cleanup_fclose_ FILE *original = NULL; group_path = fix_root("/etc/group"); - r = fopen_temporary(group_path, &group, &group_tmp); + r = fopen_temporary_label("/etc/group", group_path, &group, &group_tmp); if (r < 0) goto finish; @@ -385,7 +391,7 @@ static int write_files(void) { _cleanup_fclose_ FILE *original = NULL; passwd_path = fix_root("/etc/passwd"); - r = fopen_temporary(passwd_path, &passwd, &passwd_tmp); + r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp); if (r < 0) goto finish; @@ -464,13 +470,13 @@ static int write_files(void) { /* Make a backup of the old files */ if (group && group_changed) { - r = make_backup(group_path); + r = make_backup("/etc/group", group_path); if (r < 0) goto finish; } if (passwd) { - r = make_backup(passwd_path); + r = make_backup("/etc/passwd", passwd_path); if (r < 0) goto finish; } @@ -1095,6 +1101,9 @@ static bool valid_user_group_name(const char *u) { if ((size_t) (i-u) > (size_t) sz) return false; + if ((size_t) (i-u) > UT_NAMESIZE - 1) + return false; + return true; } @@ -1103,7 +1112,11 @@ static bool valid_gecos(const char *d) { if (!utf8_is_valid(d)) return false; - if (strpbrk(d, ":\n")) + if (string_has_cc(d, NULL)) + return false; + + /* Colons are used as field separators, and hence not OK */ + if (strchr(d, ':')) return false; return true; @@ -1312,6 +1325,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { h = groups; break; + default: + return -EBADMSG; } i->type = action[0]; @@ -1515,7 +1530,11 @@ int main(int argc, char *argv[]) { umask(0022); - r = 0; + r = label_init(NULL); + if (r < 0) { + log_error("SELinux setup failed: %s", strerror(-r)); + goto finish; + } if (optind < argc) { int j; diff --git a/src/test/test-util.c b/src/test/test-util.c index 44921bd..ed91a67 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -731,6 +731,20 @@ static void test_filename_is_safe(void) { assert_se(filename_is_safe("o.o")); } +static void test_string_has_cc(void) { + assert_se(string_has_cc("abc\1", NULL)); + assert_se(string_has_cc("abc\x7f", NULL)); + assert_se(string_has_cc("abc\x7f", NULL)); + assert_se(string_has_cc("abc\t\x7f", "\t")); + assert_se(string_has_cc("abc\t\x7f", "\t")); + assert_se(string_has_cc("\x7f", "\t")); + assert_se(string_has_cc("\x7f", "\t\a")); + + assert_se(!string_has_cc("abc\t\t", "\t")); + assert_se(!string_has_cc("abc\t\t\a", "\t\a")); + assert_se(!string_has_cc("a\ab\tc", "\t\a")); +} + static void test_ascii_strlower(void) { char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK"; assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk")); @@ -937,6 +951,7 @@ int main(int argc, char *argv[]) { test_log2i(); test_foreach_string(); test_filename_is_safe(); + test_string_has_cc(); test_ascii_strlower(); test_files_same(); test_is_valid_documentation_url(); diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c index 27f6b2d..19af9f9 100644 --- a/src/timesync/timesyncd.c +++ b/src/timesync/timesyncd.c @@ -1044,10 +1044,6 @@ static int manager_new(Manager **ret) { if (r < 0) return r; - r = manager_clock_watch_setup(m); - if (r < 0) - return r; - *ret = m; m = NULL; diff --git a/src/udev/accelerometer/accelerometer.c b/src/udev/accelerometer/accelerometer.c index 925d38d..32adf27 100644 --- a/src/udev/accelerometer/accelerometer.c +++ b/src/udev/accelerometer/accelerometer.c @@ -180,7 +180,7 @@ get_prev_orientation(struct udev_device *dev) return string_to_orientation(value); } -#define SET_AXIS(axis, code_) if (ev[i].code == code_) { if (got_##axis == 0) { axis = ev[i].value; got_##axis = true; } } +#define READ_AXIS(axis, var) { memzero(&abs_info, sizeof(abs_info)); r = ioctl(fd, EVIOCGABS(axis), &abs_info); if (r < 0) return; var = abs_info.value; } /* accelerometers */ static void test_orientation(struct udev *udev, @@ -189,10 +189,9 @@ static void test_orientation(struct udev *udev, { OrientationUp old, new; _cleanup_close_ int fd = -1; - struct input_event ev[64]; - bool got_syn = false; - bool got_x = false, got_y = false, got_z = false; + struct input_absinfo abs_info; int x = 0, y = 0, z = 0; + int r; char text[64]; old = get_prev_orientation(dev); @@ -201,30 +200,10 @@ static void test_orientation(struct udev *udev, if (fd < 0) return; - while (1) { - int i, r; - - r = read(fd, ev, sizeof(struct input_event) * 64); - - if (r < (int) sizeof(struct input_event)) - return; - - for (i = 0; i < r / (int) sizeof(struct input_event); i++) { - if (got_syn) { - if (ev[i].type == EV_ABS) { - SET_AXIS(x, ABS_X); - SET_AXIS(y, ABS_Y); - SET_AXIS(z, ABS_Z); - } - } - if (ev[i].type == EV_SYN && ev[i].code == SYN_REPORT) - got_syn = true; - if (got_x && got_y && got_z) - goto read_dev; - } - } + READ_AXIS(ABS_X, x); + READ_AXIS(ABS_Y, y); + READ_AXIS(ABS_Z, z); -read_dev: new = orientation_calc(old, x, y, z); snprintf(text, sizeof(text), "ID_INPUT_ACCELEROMETER_ORIENTATION=%s", orientation_to_string(new)); diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index b8650a6..5a45c53 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -383,7 +383,9 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_dev case MACPOLICY_PERSISTENT: if (mac_is_random(device)) { r = get_mac(device, false, &generated_mac); - if (r < 0) + if (r == -ENOENT) + break; + else if (r < 0) return r; mac = &generated_mac; } @@ -391,7 +393,9 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_dev case MACPOLICY_RANDOM: if (!mac_is_random(device)) { r = get_mac(device, true, &generated_mac); - if (r < 0) + if (r == -ENOENT) + break; + else if (r < 0) return r; mac = &generated_mac; } diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c index 10ba85c..b199a68 100644 --- a/src/update-done/update-done.c +++ b/src/update-done/update-done.c @@ -20,6 +20,7 @@ ***/ #include "util.h" +#include "label.h" static int apply_timestamp(const char *path, struct timespec *ts) { struct timespec twice[2]; @@ -51,10 +52,20 @@ static int apply_timestamp(const char *path, struct timespec *ts) { } else if (errno == ENOENT) { _cleanup_close_ int fd = -1; + int r; /* The timestamp file doesn't exist yet? Then let's create it. */ + r = label_context_set(path, S_IFREG); + if (r < 0) { + log_error("Failed to set SELinux context for %s: %s", + path, strerror(-r)); + return r; + } + fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); + label_context_clear(); + if (fd < 0) { if (errno == EROFS) { @@ -83,7 +94,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) { int main(int argc, char *argv[]) { struct stat st; - int r, q; + int r, q = 0; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); @@ -94,11 +105,15 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - r = apply_timestamp("/etc/.updated", &st.st_mtim); + r = label_init(NULL); + if (r < 0) { + log_error("SELinux setup failed: %s", strerror(-r)); + goto finish; + } + r = apply_timestamp("/etc/.updated", &st.st_mtim); q = apply_timestamp("/var/.updated", &st.st_mtim); - if (q < 0 && r == 0) - r = q; - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +finish: + return r < 0 || q < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index e0c4050..645b1e6 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -238,12 +238,10 @@ static void font_copy_to_all_vcs(int fd) { int main(int argc, char **argv) { const char *vc; - char *vc_keymap = NULL; - char *vc_keymap_toggle = NULL; - char *vc_font = NULL; - char *vc_font_map = NULL; - char *vc_font_unimap = NULL; - int fd = -1; + _cleanup_free_ char + *vc_keymap = NULL, *vc_keymap_toggle = NULL, + *vc_font = NULL, *vc_font_map = NULL, *vc_font_unimap = NULL; + _cleanup_close_ int fd = -1; bool utf8; pid_t font_pid = 0, keymap_pid = 0; bool font_copy = false; @@ -265,12 +263,12 @@ int main(int argc, char **argv) { fd = open_terminal(vc, O_RDWR|O_CLOEXEC); if (fd < 0) { log_error("Failed to open %s: %m", vc); - goto finish; + return EXIT_FAILURE; } if (!is_vconsole(fd)) { log_error("Device %s is not a virtual console.", vc); - goto finish; + return EXIT_FAILURE; } utf8 = is_locale_utf8(); @@ -305,27 +303,27 @@ int main(int argc, char **argv) { else disable_utf8(fd); - r = EXIT_FAILURE; - if (keymap_load(vc, vc_keymap, vc_keymap_toggle, utf8, &keymap_pid) >= 0 && - font_load(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid) >= 0) - r = EXIT_SUCCESS; - -finish: - if (keymap_pid > 0) - wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid); + r = font_load(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid); + if (r < 0) { + log_error("Failed to start " KBD_SETFONT ": %s", strerror(-r)); + return EXIT_FAILURE; + } - if (font_pid > 0) { + if (font_pid > 0) wait_for_terminate_and_warn(KBD_SETFONT, font_pid); - if (font_copy) - font_copy_to_all_vcs(fd); + + r = keymap_load(vc, vc_keymap, vc_keymap_toggle, utf8, &keymap_pid); + if (r < 0) { + log_error("Failed to start " KBD_LOADKEYS ": %s", strerror(-r)); + return EXIT_FAILURE; } - free(vc_keymap); - free(vc_font); - free(vc_font_map); - free(vc_font_unimap); + if (keymap_pid > 0) + wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid); - safe_close(fd); + /* Only copy the font when we started setfont successfully */ + if (font_copy && font_pid > 0) + font_copy_to_all_vcs(fd); - return r; + return EXIT_SUCCESS; } diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in index d5795a3..d5f600e 100644 --- a/sysctl.d/50-coredump.conf.in +++ b/sysctl.d/50-coredump.conf.in @@ -5,6 +5,8 @@ # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. -# See sysctl.d(5) and core(5) for for details. +# See sysctl.d(5) for the description of the files in this directory, +# and systemd-coredump(8) and core(5) for the explanation of the +# setting below. kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %p %u %g %s %t %e diff --git a/units/emergency.service.in b/units/emergency.service.in index 94c090f..91fc1bb 100644 --- a/units/emergency.service.in +++ b/units/emergency.service.in @@ -17,8 +17,7 @@ Environment=HOME=/root WorkingDirectory=/root ExecStartPre=-/bin/plymouth quit ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" to try again\\nto boot into default mode.' -ExecStart=-/sbin/sulogin -ExecStopPost=@SYSTEMCTL@ --fail --no-block default +ExecStart=-/bin/sh -c "/sbin/sulogin; @SYSTEMCTL@ --fail --no-block default" Type=idle StandardInput=tty-force StandardOutput=inherit diff --git a/units/kmod-static-nodes.service.in b/units/kmod-static-nodes.service.in index 368f980..0934a87 100644 --- a/units/kmod-static-nodes.service.in +++ b/units/kmod-static-nodes.service.in @@ -9,7 +9,7 @@ Description=Create list of required static device nodes for the current kernel DefaultDependencies=no Before=sysinit.target systemd-tmpfiles-setup-dev.service -ConditionCapability=CAP_MKNOD +ConditionCapability=CAP_SYS_MODULE ConditionPathExists=/lib/modules/%v/modules.devname [Service] diff --git a/units/rescue.service.m4.in b/units/rescue.service.m4.in index 552ef89..ef54369 100644 --- a/units/rescue.service.m4.in +++ b/units/rescue.service.m4.in @@ -18,8 +18,7 @@ Environment=HOME=/root WorkingDirectory=/root ExecStartPre=-/bin/plymouth quit ExecStartPre=-/bin/echo -e 'Welcome to rescue mode! Type "systemctl default" or ^D to enter default mode.\\nType "journalctl -xb" to view system logs. Type "systemctl reboot" to reboot.' -ExecStart=-/sbin/sulogin -ExecStopPost=-@SYSTEMCTL@ --fail --no-block default +ExecStart=-/bin/sh -c "/sbin/sulogin; @SYSTEMCTL@ --fail --no-block default" Type=idle StandardInput=tty-force StandardOutput=inherit diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4 index 4ac51e7..4522d0d 100644 --- a/units/serial-getty@.service.m4 +++ b/units/serial-getty@.service.m4 @@ -25,7 +25,6 @@ IgnoreOnIsolate=yes ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM Type=idle Restart=always -RestartSec=0 UtmpIdentifier=%I TTYPath=/dev/%I TTYReset=yes diff --git a/units/sys-kernel-config.mount b/units/sys-kernel-config.mount index 020101c..21648ef 100644 --- a/units/sys-kernel-config.mount +++ b/units/sys-kernel-config.mount @@ -11,6 +11,7 @@ Documentation=https://www.kernel.org/doc/Documentation/filesystems/configfs/conf Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems DefaultDependencies=no ConditionPathExists=/sys/kernel/config +ConditionCapability=CAP_SYS_RAWIO After=systemd-modules-load.service Before=sysinit.target diff --git a/units/sys-kernel-debug.mount b/units/sys-kernel-debug.mount index 5369728..1e94387 100644 --- a/units/sys-kernel-debug.mount +++ b/units/sys-kernel-debug.mount @@ -11,6 +11,7 @@ Documentation=https://www.kernel.org/doc/Documentation/filesystems/debugfs.txt Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems DefaultDependencies=no ConditionPathExists=/sys/kernel/debug +ConditionCapability=CAP_SYS_RAWIO Before=sysinit.target [Mount] diff --git a/units/systemd-tmpfiles-setup-dev.service.in b/units/systemd-tmpfiles-setup-dev.service.in index b9cfc53..06346d3 100644 --- a/units/systemd-tmpfiles-setup-dev.service.in +++ b/units/systemd-tmpfiles-setup-dev.service.in @@ -12,7 +12,7 @@ DefaultDependencies=no Conflicts=shutdown.target After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-sysusers.service Before=sysinit.target local-fs-pre.target systemd-udevd.service shutdown.target -ConditionCapability=CAP_MKNOD +ConditionCapability=CAP_SYS_MODULE [Service] Type=oneshot