summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTollef Fog Heen <tfheen@err.no>2011-10-12 08:40:18 +0200
committerTollef Fog Heen <tfheen@err.no>2011-10-12 08:40:18 +0200
commit9f539f05b7b9f6ec57e0a195b550a4ed514a1354 (patch)
tree47bb694f6c54a05b9d03b26b935c096fd2b377ca
parentbaf8bb13719693fbc4be438dd3c358f2f9d861cd (diff)
parentd2134abdd5a21bb7e4b307f403d890901628fcf9 (diff)
downloadsystemd-9f539f05b7b9f6ec57e0a195b550a4ed514a1354.tar.gz
Merge commit 'v37'
-rw-r--r--Makefile.am14
-rw-r--r--TODO9
-rw-r--r--configure.ac2
-rw-r--r--man/systemctl.xml15
-rw-r--r--man/systemd.exec.xml5
-rw-r--r--man/systemd.service.xml36
-rw-r--r--man/systemd.special.xml.in26
-rw-r--r--man/systemd.unit.xml29
-rw-r--r--po/pl.po10
-rw-r--r--src/condition.c36
-rw-r--r--src/condition.h1
-rwxr-xr-xsrc/generate-kbd-model-map33
-rw-r--r--src/hashmap.c8
-rw-r--r--src/hostname-setup.c4
-rw-r--r--src/kbd-model-map72
-rw-r--r--src/load-fragment-gperf.gperf.m41
-rw-r--r--src/localed.c800
-rw-r--r--src/logind-dbus.c11
-rw-r--r--src/mount.c6
-rw-r--r--src/org.freedesktop.locale1.policy.in10
-rw-r--r--src/pager.c18
-rw-r--r--src/readahead-common.h2
-rw-r--r--src/sd-login.h4
-rw-r--r--src/service.c1
-rw-r--r--src/special.h2
-rw-r--r--src/systemctl.c92
-rwxr-xr-xsrc/systemd-analyze41
-rw-r--r--src/timedated.c20
-rw-r--r--src/tmpfiles.c1
-rw-r--r--src/util.c27
-rw-r--r--src/util.h2
-rw-r--r--src/vconsole-setup.c4
-rw-r--r--units/local-fs-pre.target11
-rw-r--r--units/remote-fs-pre.target15
-rw-r--r--units/remount-rootfs.service3
-rw-r--r--units/systemd-logind.service.in4
-rw-r--r--units/systemd-remount-api-vfs.service.in3
-rw-r--r--units/systemd-stdout-syslog-bridge.service.in4
38 files changed, 1279 insertions, 103 deletions
diff --git a/Makefile.am b/Makefile.am
index 66a64fd4fa..dabe32ac46 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,7 @@ ACLOCAL_AMFLAGS = -I m4
SUBDIRS = po
LIBSYSTEMD_LOGIN_CURRENT=0
-LIBSYSTEMD_LOGIN_REVISION=5
+LIBSYSTEMD_LOGIN_REVISION=6
LIBSYSTEMD_LOGIN_AGE=0
LIBSYSTEMD_DAEMON_CURRENT=0
@@ -76,6 +76,7 @@ AM_CPPFLAGS = \
-DSYSTEM_GENERATOR_PATH=\"$(systemgeneratordir)\" \
-DUSER_GENERATOR_PATH=\"$(usergeneratordir)\" \
-DSYSTEM_SHUTDOWN_PATH=\"$(systemshutdowndir)\" \
+ -DSYSTEMD_KBD_MODEL_MAP=\"$(pkgdatadir)/kbd-model-map\" \
-I $(top_srcdir)/src
if TARGET_GENTOO
@@ -336,7 +337,9 @@ dist_systemunit_DATA = \
units/halt.target \
units/kexec.target \
units/local-fs.target \
+ units/local-fs-pre.target \
units/remote-fs.target \
+ units/remote-fs-pre.target \
units/cryptsetup.target \
units/network.target \
units/nss-lookup.target \
@@ -1031,6 +1034,12 @@ systemd_localed_LDADD = \
libsystemd-daemon.la \
$(DBUS_LIBS)
+dist_pkgdata_DATA = \
+ src/kbd-model-map
+
+dist_noinst_SCRIPT = \
+ src/generate-kbd-model-map
+
systemd_timedated_SOURCES = \
src/timedated.c \
src/dbus-common.c \
@@ -2016,3 +2025,6 @@ upload: all distcheck
git-tag:
git tag "v$(VERSION)" -m "systemd $(VERSION)"
+
+update-kbd-model-map:
+ src/generate-kbd-model-map > src/kbd-model-map
diff --git a/TODO b/TODO
index 98556378af..9149018134 100644
--- a/TODO
+++ b/TODO
@@ -15,8 +15,17 @@ Bugfixes:
automount points even when the original .automount file did not exist
anymore. Only the .mount unit was still around.
+* make polkit checks async
+
Features:
+* unset container= in PID1?
+
+* if we can not get user quota for tmpfs, mount a separate tmpfs instance
+ for every user in /run/user/$USER with a configured maximum size
+
+* default to actual 32bit PIDs, via /proc/sys/kernel/pid_max
+
* add an option to make mounts private/shareable and so on, enable this for root by default
* internal restart counter for units (focus on auto-respawn)
diff --git a/configure.ac b/configure.ac
index 18dc3fe36a..0ec6f69bc8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
AC_PREREQ(2.63)
-AC_INIT([systemd],[36],[systemd-devel@lists.freedesktop.org])
+AC_INIT([systemd],[37],[systemd-devel@lists.freedesktop.org])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 468141c2bd..5adee45163 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -198,6 +198,14 @@
</varlistentry>
<varlistentry>
+ <term><option>--no-legend</option></term>
+
+ <listitem><para>Do not print a legend, i.e.
+ the column headers and the footer with hints.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--no-pager</option></term>
<listitem><para>Do not pipe output into a
@@ -595,6 +603,13 @@
</varlistentry>
<varlistentry>
+ <term><command>list-unit-files</command></term>
+
+ <listitem><para>List installed unit files.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><command>enable [NAME...]</command></term>
<listitem><para>Enable one or more
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 609484b3a3..230c4a31f7 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -279,6 +279,11 @@
assignments. Empty lines and lines
starting with ; or # will be ignored,
which may be used for commenting. The
+ parser strips leading and
+ trailing whitespace from the values
+ of assignments, unless you use
+ double quotes (").
+ The
argument passed should be an absolute
file name, optionally prefixed with
"-", which indicates that if the file
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 4f1102021f..7b6f12d069 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -311,20 +311,28 @@
main process of the daemon. The
command line accepts % specifiers as
described in
- <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>. On
- top of that basic environment variable
- substitution is supported, where
- <literal>${FOO}</literal> is replaced
- by the string value of the environment
- variable of the same name. Also
- <literal>$FOO</literal> may appear as
- separate word on the command line in
- which case the variable is replaced by
- its value split at whitespaces. Note
- that the first argument (i.e. the
- binary to execute) may not be a
- variable, and must be a literal and
- absolute path name.</para></listitem>
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
+ <para>On top of that basic environment
+ variable substitution is
+ supported. Use
+ <literal>${FOO}</literal> as part of a
+ word, or as word of its own on the
+ command line, in which case it will be
+ replaced by the value of the
+ environment variable including all
+ whitespace it contains, resulting in a
+ single argument. Use
+ <literal>$FOO</literal> as a separate
+ word on the command line, in which
+ case it will be replaced by the value
+ of the environment variable split up
+ at whitespace, resulting in no or more
+ arguments. Note that the first
+ argument (i.e. the program to execute)
+ may not be a variable, and must be a
+ literal and absolute path
+ name.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.special.xml.in b/man/systemd.special.xml.in
index 218754051e..116a43ccfb 100644
--- a/man/systemd.special.xml.in
+++ b/man/systemd.special.xml.in
@@ -59,6 +59,7 @@
<filename>halt.target</filename>,
<filename>kbrequest.target</filename>,
<filename>local-fs.target</filename>,
+ <filename>local-fs-pre.target</filename>,
<filename>mail-transfer-agent.target</filename>,
<filename>multi-user.target</filename>,
<filename>network.target</filename>,
@@ -66,6 +67,7 @@
<filename>poweroff.target</filename>,
<filename>reboot.target</filename>,
<filename>remote-fs.target</filename>,
+ <filename>remote-fs-pre.target</filename>,
<filename>rescue.target</filename>,
<filename>rpcbind.target</filename>,
<filename>runlevel2.target</filename>,
@@ -261,6 +263,18 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>local-fs-pre.target</filename></term>
+ <listitem>
+ <para>This target unit is
+ automatically ordered before
+ all local mount points marked
+ with <option>auto</option>
+ (see above). It can be used to
+ execute certain units before
+ all local mounts.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><filename>mail-transfer-agent.target</filename></term>
<listitem>
<para>The mail transfer agent
@@ -374,6 +388,18 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>remote-fs-pre.target</filename></term>
+ <listitem>
+ <para>This target unit is
+ automatically ordered before
+ all remote mount points marked
+ with <option>auto</option>
+ (see above). It can be used to
+ execute certain units before
+ all remote mounts.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><filename>rescue.target</filename></term>
<listitem>
<para>A special target unit
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index bf8de322dd..897f99f24c 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -121,8 +121,9 @@
<para>If a line starts with <option>.include</option>
followed by a file name, the specified file will be
- read as if its contents were listed in place of the
- <option>.include</option> directive.</para>
+ parsed at this point. Make sure that the file that is
+ included has the appropiate section headers before
+ any directives.</para>
<para>Along with a unit file
<filename>foo.service</filename> a directory
@@ -672,6 +673,7 @@
<term><varname>ConditionKernelCommandLine=</varname></term>
<term><varname>ConditionVirtualization=</varname></term>
<term><varname>ConditionSecurity=</varname></term>
+ <term><varname>ConditionCapability=</varname></term>
<term><varname>ConditionNull=</varname></term>
<listitem><para>Before starting a unit
@@ -748,9 +750,9 @@
value to check if being executed in
any virtualized environment, or one of
<varname>vm</varname> and
- <varname>container</varname> to test against
- a specific type of virtualization
- solution, or one of
+ <varname>container</varname> to test
+ against a specific type of
+ virtualization solution, or one of
<varname>qemu</varname>,
<varname>kvm</varname>,
<varname>vmware</varname>,
@@ -774,7 +776,19 @@
system. Currently the only recognized
value is <varname>selinux</varname>.
The test may be negated by prepending
- an exclamation mark. Finally,
+ an exclamation
+ mark. <varname>ConditionCapability=</varname>
+ may be used to check whether the given
+ capability exists in the capability
+ bounding set of the service manager
+ (i.e. this does not check whether
+ capability is actually available in
+ the permitted or effective sets, see
+ <citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details). Pass a capability name
+ such as <literal>CAP_MKNOD</literal>,
+ possibly prefixed with an exclamation
+ mark to negate the check. Finally,
<varname>ConditionNull=</varname> may
be used to add a constant condition
check value to the unit. It takes a
@@ -931,7 +945,8 @@
<citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.path</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.snapshot</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.snapshot</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/po/pl.po b/po/pl.po
index 52a21c87bb..38168643eb 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -53,7 +53,7 @@ msgstr "Ustawienie lokalizacji systemu"
#: ../src/org.freedesktop.login1.policy.in.h:1
msgid "Allow attaching devices to seats"
-msgstr "Zezwolenie na podłączanie urządzeń do siedzeń"
+msgstr "Zezwolenie na podłączanie urządzeń do stanowisk"
#: ../src/org.freedesktop.login1.policy.in.h:2
msgid "Allow non-logged-in users to run programs"
@@ -69,8 +69,8 @@ msgstr ""
#: ../src/org.freedesktop.login1.policy.in.h:4
msgid "Authentication is required to allow attaching a device to a seat"
msgstr ""
-"Wymagane jest uwierzytelnienie, aby zezwolić na podłączanie urządzeń do "
-"siedzeń"
+"Wymagane jest uwierzytelnienie, aby zezwolić na podłączenie urządzenia do "
+"stanowiska"
#: ../src/org.freedesktop.login1.policy.in.h:5
msgid "Authentication is required to allow powering off the system"
@@ -103,11 +103,11 @@ msgid ""
"seats"
msgstr ""
"Wymagane jest uwierzytelnienie, aby zezwolić na ponowne ustawianie sposobu "
-"podłączenia urządzeń do siedzeń"
+"podłączenia urządzeń do stanowisk"
#: ../src/org.freedesktop.login1.policy.in.h:10
msgid "Flush device to seat attachments"
-msgstr "Czyszczenie podłączeń urządzeń do siedzeń"
+msgstr "Usunięcie podłączenia urządzeń do stanowisk"
#: ../src/org.freedesktop.login1.policy.in.h:11
msgid "Power off the system"
diff --git a/src/condition.c b/src/condition.c
index e978656772..f18c45421a 100644
--- a/src/condition.c
+++ b/src/condition.c
@@ -23,6 +23,7 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
+#include <sys/capability.h>
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
@@ -148,7 +149,7 @@ static bool test_virtualization(const char *parameter) {
return true;
/* Finally compare id */
- return streq(parameter, id);
+ return v > 0 && streq(parameter, id);
}
static bool test_security(const char *parameter) {
@@ -159,6 +160,36 @@ static bool test_security(const char *parameter) {
return false;
}
+static bool test_capability(const char *parameter) {
+ cap_value_t value;
+ FILE *f;
+ char line[LINE_MAX];
+ unsigned long long capabilities = (unsigned long long) -1;
+
+ /* If it's an invalid capability, we don't have it */
+
+ if (cap_from_name(parameter, &value) < 0)
+ return false;
+
+ /* If it's a valid capability we default to assume
+ * that we have it */
+
+ f = fopen("/proc/self/status", "re");
+ if (!f)
+ return true;
+
+ while (fgets(line, sizeof(line), f)) {
+ truncate_nl(line);
+
+ if (startswith(line, "CapBnd:")) {
+ (void) sscanf(line+7, "%llx", &capabilities);
+ break;
+ }
+ }
+
+ return !!(capabilities & (1ULL << value));
+}
+
bool condition_test(Condition *c) {
assert(c);
@@ -214,6 +245,9 @@ bool condition_test(Condition *c) {
case CONDITION_SECURITY:
return test_security(c->parameter) == !c->negate;
+ case CONDITION_CAPABILITY:
+ return test_capability(c->parameter) == !c->negate;
+
case CONDITION_NULL:
return !c->negate;
diff --git a/src/condition.h b/src/condition.h
index dd65aa6054..71b1c6761e 100644
--- a/src/condition.h
+++ b/src/condition.h
@@ -37,6 +37,7 @@ typedef enum ConditionType {
CONDITION_KERNEL_COMMAND_LINE,
CONDITION_VIRTUALIZATION,
CONDITION_SECURITY,
+ CONDITION_CAPABILITY,
CONDITION_NULL,
_CONDITION_TYPE_MAX,
_CONDITION_TYPE_INVALID = -1
diff --git a/src/generate-kbd-model-map b/src/generate-kbd-model-map
new file mode 100755
index 0000000000..624c5179fa
--- /dev/null
+++ b/src/generate-kbd-model-map
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+import sys
+import system_config_keyboard.keyboard_models
+
+def strdash(s):
+ return s.strip() or '-'
+
+def tab_extend(s, n=1):
+ s = strdash(s)
+ k = len(s) // 8
+
+ if k >= n:
+ f = 1
+ else:
+ f = n - k
+
+ return s + '\t'*f
+
+
+models = system_config_keyboard.keyboard_models.KeyboardModels().get_models()
+
+print "# Generated from system-config-keyboard's model list"
+print "# consolelayout\t\txlayout\txmodel\t\txvariant\txoptions"
+
+for key, value in reversed(models.items()):
+ options = "terminate:ctrl_alt_bksp"
+ if value[4]:
+ options += ',' + value[4]
+
+ print ''.join((tab_extend(key, 3), tab_extend(value[1]),
+ tab_extend(value[2], 2), tab_extend(value[3], 2),
+ options))
diff --git a/src/hashmap.c b/src/hashmap.c
index 0d89da4614..95ea45da48 100644
--- a/src/hashmap.c
+++ b/src/hashmap.c
@@ -124,11 +124,13 @@ __attribute__((destructor)) static void cleanup_pool(void) {
#endif
unsigned string_hash_func(const void *p) {
- unsigned hash = 0;
- const char *c;
+ unsigned hash = 5381;
+ const signed char *c;
+
+ /* DJB's hash function */
for (c = p; *c; c++)
- hash = 31 * hash + (unsigned) *c;
+ hash = (hash << 5) + hash + (unsigned) *c;
return hash;
}
diff --git a/src/hostname-setup.c b/src/hostname-setup.c
index 57db9fbf7c..7216b75c8a 100644
--- a/src/hostname-setup.c
+++ b/src/hostname-setup.c
@@ -32,7 +32,7 @@
#if defined(TARGET_FEDORA) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MEEGO)
#define FILENAME "/etc/sysconfig/network"
-#elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE) || defined(TARGET_FRUGALWARE)
+#elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE)
#define FILENAME "/etc/HOSTNAME"
#elif defined(TARGET_ARCH)
#define FILENAME "/etc/rc.conf"
@@ -114,7 +114,7 @@ finish:
fclose(f);
return r;
-#elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE) || defined(TARGET_FRUGALWARE)
+#elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE)
return read_and_strip_hostname(FILENAME, hn);
#else
return -ENOENT;
diff --git a/src/kbd-model-map b/src/kbd-model-map
new file mode 100644
index 0000000000..a895880269
--- /dev/null
+++ b/src/kbd-model-map
@@ -0,0 +1,72 @@
+# Generated from system-config-keyboard's model list
+# consolelayout xlayout xmodel xvariant xoptions
+sg ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp
+nl nl pc105 - terminate:ctrl_alt_bksp
+mk-utf mkd,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+trq tr pc105 - terminate:ctrl_alt_bksp
+guj in,us pc105 guj terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+uk gb pc105 - terminate:ctrl_alt_bksp
+is-latin1 is pc105 - terminate:ctrl_alt_bksp
+de de pc105 - terminate:ctrl_alt_bksp
+gur gur,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+la-latin1 latam pc105 - terminate:ctrl_alt_bksp
+us us pc105+inet - terminate:ctrl_alt_bksp
+ko kr pc105 - terminate:ctrl_alt_bksp
+ro-std ro pc105 std terminate:ctrl_alt_bksp
+de-latin1 de pc105 - terminate:ctrl_alt_bksp
+tml-inscript in,us pc105 tam terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+slovene si pc105 - terminate:ctrl_alt_bksp
+hu101 hu pc105 qwerty terminate:ctrl_alt_bksp
+jp106 jp jp106 - terminate:ctrl_alt_bksp
+croat hr pc105 - terminate:ctrl_alt_bksp
+ben-probhat in,us pc105 ben_probhat terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+fi-latin1 fi pc105 - terminate:ctrl_alt_bksp
+it2 it pc105 - terminate:ctrl_alt_bksp
+hu hu pc105 - terminate:ctrl_alt_bksp
+sr-latin rs pc105 latin terminate:ctrl_alt_bksp
+fi fi pc105 - terminate:ctrl_alt_bksp
+fr_CH ch pc105 fr terminate:ctrl_alt_bksp
+dk-latin1 dk pc105 - terminate:ctrl_alt_bksp
+fr fr pc105 - terminate:ctrl_alt_bksp
+it it pc105 - terminate:ctrl_alt_bksp
+tml-uni in,us pc105 tam_TAB terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ua-utf ua,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+fr-latin1 fr pc105 - terminate:ctrl_alt_bksp
+sg-latin1 ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp
+be-latin1 be pc105 - terminate:ctrl_alt_bksp
+dk dk pc105 - terminate:ctrl_alt_bksp
+fr-pc fr pc105 - terminate:ctrl_alt_bksp
+bg_pho-utf8 bg,us pc105 ,phonetic terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+it-ibm it pc105 - terminate:ctrl_alt_bksp
+cz-us-qwertz cz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ar-digits ara,us pc105 digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+br-abnt2 br abnt2 - terminate:ctrl_alt_bksp
+ro ro pc105 - terminate:ctrl_alt_bksp
+us-acentos us pc105 intl terminate:ctrl_alt_bksp
+pt-latin1 pt pc105 - terminate:ctrl_alt_bksp
+ro-std-cedilla ro pc105 std_cedilla terminate:ctrl_alt_bksp
+tj tj pc105 - terminate:ctrl_alt_bksp
+ar-qwerty ara,us pc105 qwerty terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ar-azerty-digits ara,us pc105 azerty_digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ben in,us pc105 ben terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+de-latin1-nodeadkeys de pc105 nodeadkeys terminate:ctrl_alt_bksp
+no no pc105 - terminate:ctrl_alt_bksp
+bg_bds-utf8 bg,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+dvorak us pc105 dvorak terminate:ctrl_alt_bksp
+ru ru,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+cz-lat2 cz pc105 qwerty terminate:ctrl_alt_bksp
+pl2 pl pc105 - terminate:ctrl_alt_bksp
+es es pc105 - terminate:ctrl_alt_bksp
+ro-cedilla ro pc105 cedilla terminate:ctrl_alt_bksp
+ie ie pc105 - terminate:ctrl_alt_bksp
+ar-azerty ara,us pc105 azerty terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ar-qwerty-digits ara,us pc105 qwerty_digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+et ee pc105 - terminate:ctrl_alt_bksp
+sk-qwerty sk pc105 - terminate:ctrl_alt_bksp,qwerty
+dev dev,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+fr-latin9 fr pc105 latin9 terminate:ctrl_alt_bksp
+fr_CH-latin1 ch pc105 fr terminate:ctrl_alt_bksp
+cf ca(fr) pc105 - terminate:ctrl_alt_bksp
+sv-latin1 se pc105 - terminate:ctrl_alt_bksp
+sr-cy rs pc105 - terminate:ctrl_alt_bksp
+gr gr,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
diff --git a/src/load-fragment-gperf.gperf.m4 b/src/load-fragment-gperf.gperf.m4
index 7749b88dfb..41797d20c0 100644
--- a/src/load-fragment-gperf.gperf.m4
+++ b/src/load-fragment-gperf.gperf.m4
@@ -119,6 +119,7 @@ Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_F
Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, 0
Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, 0
Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, 0
+Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, 0
Unit.ConditionNull, config_parse_unit_condition_null, 0, 0
m4_dnl
Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file)
diff --git a/src/localed.c b/src/localed.c
index fbb5a41d1a..c6b48de5f9 100644
--- a/src/localed.c
+++ b/src/localed.c
@@ -34,10 +34,30 @@
#define INTERFACE \
" <interface name=\"org.freedesktop.locale1\">\n" \
" <property name=\"Locale\" type=\"as\" access=\"read\"/>\n" \
+ " <property name=\"VConsoleKeymap\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"VConsoleKeymapToggle\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"X11Layout\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"X11Model\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"X11Variant\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"X11Options\" type=\"s\" access=\"read\"/>\n" \
" <method name=\"SetLocale\">\n" \
" <arg name=\"locale\" type=\"as\" direction=\"in\"/>\n" \
" <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
" </method>\n" \
+ " <method name=\"SetVConsoleKeyboard\">\n" \
+ " <arg name=\"keymap\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"keymap_toggle\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"convert\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetX11Keyboard\">\n" \
+ " <arg name=\"layout\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"model\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"variant\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"options\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"convert\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
" </interface>\n"
#define INTROSPECTION \
@@ -109,9 +129,28 @@ static char *data[_PROP_MAX] = {
NULL
};
+static char *x11_layout = NULL, *x11_model = NULL, *x11_variant = NULL, *x11_options = NULL;
+static char *vc_keymap = NULL, *vc_keymap_toggle = NULL;
+
static usec_t remain_until = 0;
-static void free_data(void) {
+static int free_and_set(char **s, const char *v) {
+ int r;
+ char *t;
+
+ assert(s);
+
+ r = strdup_or_null(isempty(v) ? NULL : v, &t);
+ if (r < 0)
+ return r;
+
+ free(*s);
+ *s = t;
+
+ return 0;
+}
+
+static void free_data_locale(void) {
int p;
for (p = 0; p < _PROP_MAX; p++) {
@@ -120,6 +159,22 @@ static void free_data(void) {
}
}
+static void free_data_x11(void) {
+ free(x11_layout);
+ free(x11_model);
+ free(x11_variant);
+ free(x11_options);
+
+ x11_layout = x11_model = x11_variant = x11_options = NULL;
+}
+
+static void free_data_vconsole(void) {
+ free(vc_keymap);
+ free(vc_keymap_toggle);
+
+ vc_keymap = vc_keymap_toggle = NULL;
+}
+
static void simplify(void) {
int p;
@@ -130,10 +185,10 @@ static void simplify(void) {
}
}
-static int read_data(void) {
+static int read_data_locale(void) {
int r;
- free_data();
+ free_data_locale();
r = parse_env_file("/etc/locale.conf", NEWLINE,
"LANG", &data[PROP_LANG],
@@ -181,7 +236,129 @@ static int read_data(void) {
return r;
}
-static int write_data(void) {
+static void free_data(void) {
+ free_data_locale();
+ free_data_vconsole();
+ free_data_x11();
+}
+
+static int read_data_vconsole(void) {
+ int r;
+
+ free_data_vconsole();
+
+ r = parse_env_file("/etc/vconsole.conf", NEWLINE,
+ "KEYMAP", &vc_keymap,
+ "KEYMAP_TOGGLE", &vc_keymap_toggle,
+ NULL);
+
+ if (r < 0 && r != -ENOENT)
+ return r;
+
+ return 0;
+}
+
+static int read_data_x11(void) {
+ FILE *f;
+ char line[LINE_MAX];
+ bool in_section = false;
+
+ free_data_x11();
+
+ f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
+ if (!f) {
+ if (errno == ENOENT) {
+
+#ifdef TARGET_FEDORA
+ f = fopen("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf", "re");
+ if (!f) {
+ if (errno == ENOENT)
+ return 0;
+ else
+ return -errno;
+ }
+#else
+ return 0;
+#endif
+
+ } else
+ return -errno;
+ }
+
+ while (fgets(line, sizeof(line), f)) {
+ char *l;
+
+ char_array_0(line);
+ l = strstrip(line);
+
+ if (l[0] == 0 || l[0] == '#')
+ continue;
+
+ if (in_section && first_word(l, "Option")) {
+ char **a;
+
+ a = strv_split_quoted(l);
+ if (!a) {
+ fclose(f);
+ return -ENOMEM;
+ }
+
+ if (strv_length(a) == 3) {
+
+ if (streq(a[1], "XkbLayout")) {
+ free(x11_layout);
+ x11_layout = a[2];
+ a[2] = NULL;
+ } else if (streq(a[1], "XkbModel")) {
+ free(x11_model);
+ x11_model = a[2];
+ a[2] = NULL;
+ } else if (streq(a[1], "XkbVariant")) {
+ free(x11_variant);
+ x11_variant = a[2];
+ a[2] = NULL;
+ } else if (streq(a[1], "XkbOptions")) {
+ free(x11_options);
+ x11_options = a[2];
+ a[2] = NULL;
+ }
+ }
+
+ strv_free(a);
+
+ } else if (!in_section && first_word(l, "Section")) {
+ char **a;
+
+ a = strv_split_quoted(l);
+ if (!a) {
+ fclose(f);
+ return -ENOMEM;
+ }
+
+ if (strv_length(a) == 2 && streq(a[1], "InputClass"))
+ in_section = true;
+
+ strv_free(a);
+ } else if (in_section && first_word(l, "EndSection"))
+ in_section = false;
+ }
+
+ fclose(f);
+
+ return 0;
+}
+
+static int read_data(void) {
+ int r, q, p;
+
+ r = read_data_locale();
+ q = read_data_vconsole();
+ p = read_data_x11();
+
+ return r < 0 ? r : q < 0 ? q : p;
+}
+
+static int write_data_locale(void) {
int r, p;
char **l = NULL;
@@ -320,6 +497,482 @@ finish:
free(l_unset);
}
+static int write_data_vconsole(void) {
+ int r;
+ char **l = NULL;
+
+ r = load_env_file("/etc/vconsole.conf", &l);
+ if (r < 0 && r != -ENOENT)
+ return r;
+
+ if (isempty(vc_keymap))
+ l = strv_env_unset(l, "KEYMAP");
+ else {
+ char *s, **u;
+
+ s = strappend("KEYMAP=", vc_keymap);
+ if (!s) {
+ strv_free(l);
+ return -ENOMEM;
+ }
+
+ u = strv_env_set(l, s);
+ free(s);
+ strv_free(l);
+
+ if (!u)
+ return -ENOMEM;
+
+ l = u;
+ }
+
+ if (isempty(vc_keymap_toggle))
+ l = strv_env_unset(l, "KEYMAP_TOGGLE");
+ else {
+ char *s, **u;
+
+ s = strappend("KEYMAP_TOGGLE=", vc_keymap_toggle);
+ if (!s) {
+ strv_free(l);
+ return -ENOMEM;
+ }
+
+ u = strv_env_set(l, s);
+ free(s);
+ strv_free(l);
+
+ if (!u)
+ return -ENOMEM;
+
+ l = u;
+ }
+
+ if (strv_isempty(l)) {
+ strv_free(l);
+
+ if (unlink("/etc/vconsole.conf") < 0)
+ return errno == ENOENT ? 0 : -errno;
+
+ return 0;
+ }
+
+ r = write_env_file("/etc/vconsole.conf", l);
+ strv_free(l);
+
+ return r;
+}
+
+static int write_data_x11(void) {
+ FILE *f;
+ char *temp_path;
+ int r;
+
+ if (isempty(x11_layout) &&
+ isempty(x11_model) &&
+ isempty(x11_variant) &&
+ isempty(x11_options)) {
+
+#ifdef TARGET_FEDORA
+ unlink("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf");
+
+ /* Symlink this to /dev/null, so that s-s-k (if it is
+ * still running) doesn't recreate this. */
+ symlink("/dev/null", "/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf");
+#endif
+
+ if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
+ return errno == ENOENT ? 0 : -errno;
+
+ return 0;
+ }
+
+ mkdir_parents("/etc/X11/xorg.conf.d", 0755);
+
+ r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path);
+ if (r < 0)
+ return r;
+
+ fchmod(fileno(f), 0644);
+
+ fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n"
+ "# manually too freely.\n"
+ "Section \"InputClass\"\n"
+ " Identifier \"system-keyboard\"\n"
+ " MatchIsKeyboard \"on\"\n", f);
+
+ if (!isempty(x11_layout))
+ fprintf(f, " Option \"XkbLayout\" \"%s\"\n", x11_layout);
+
+ if (!isempty(x11_model))
+ fprintf(f, " Option \"XkbModel\" \"%s\"\n", x11_model);
+
+ if (!isempty(x11_variant))
+ fprintf(f, " Option \"XkbVariant\" \"%s\"\n", x11_variant);
+
+ if (!isempty(x11_options))
+ fprintf(f, " Option \"XkbOptions\" \"%s\"\n", x11_options);
+
+ fputs("EndSection\n", f);
+ fflush(f);
+
+ if (ferror(f) || rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) {
+ r = -errno;
+ unlink("/etc/X11/xorg.conf.d/00-keyboard.conf");
+ unlink(temp_path);
+ } else {
+
+#ifdef TARGET_FEDORA
+ unlink("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf");
+
+ /* Symlink this to /dev/null, so that s-s-k (if it is
+ * still running) doesn't recreate this. */
+ symlink("/dev/null", "/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf");
+#endif
+
+ r = 0;
+ }
+
+ fclose(f);
+ free(temp_path);
+
+ return r;
+}
+
+static int load_vconsole_keymap(DBusConnection *bus, DBusError *error) {
+ DBusMessage *m = NULL, *reply = NULL;
+ const char *name = "systemd-vconsole-setup.service", *mode = "replace";
+ int r;
+ DBusError _error;
+
+ assert(bus);
+
+ if (!error) {
+ dbus_error_init(&_error);
+ error = &_error;
+ }
+
+ m = dbus_message_new_method_call(
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "RestartUnit");
+ if (!m) {
+ log_error("Could not allocate message.");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (!dbus_message_append_args(m,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &mode,
+ DBUS_TYPE_INVALID)) {
+ log_error("Could not append arguments to message.");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
+ if (!reply) {
+ log_error("Failed to issue method call: %s", bus_error_message(error));
+ r = -EIO;
+ goto finish;
+ }
+
+ r = 0;
+
+finish:
+ if (m)
+ dbus_message_unref(m);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ if (error == &_error)
+ dbus_error_free(error);
+
+ return r;
+}
+
+static char *strnulldash(const char *s) {
+ return s == NULL || *s == 0 || (s[0] == '-' && s[1] == 0) ? NULL : (char*) s;
+}
+
+static int read_next_mapping(FILE *f, unsigned *n, char ***a) {
+ assert(f);
+ assert(n);
+ assert(a);
+
+ for (;;) {
+ char line[LINE_MAX];
+ char *l, **b;
+
+ errno = 0;
+ if (!fgets(line, sizeof(line), f)) {
+
+ if (ferror(f))
+ return errno ? -errno : -EIO;
+
+ return 0;
+ }
+
+ (*n) ++;
+
+ l = strstrip(line);
+ if (l[0] == 0 || l[0] == '#')
+ continue;
+
+ b = strv_split_quoted(l);
+ if (!b)
+ return -ENOMEM;
+
+ if (strv_length(b) < 5) {
+ log_error("Invalid line "SYSTEMD_KBD_MODEL_MAP":%u, ignoring.", *n);
+ strv_free(b);
+ continue;
+
+ }
+
+ *a = b;
+ return 1;
+ }
+}
+
+static int convert_vconsole_to_x11(DBusConnection *connection) {
+ bool modified = false;
+
+ assert(connection);
+
+ if (isempty(vc_keymap)) {
+
+ modified =
+ !isempty(x11_layout) ||
+ !isempty(x11_model) ||
+ !isempty(x11_variant) ||
+ !isempty(x11_options);
+
+ free_data_x11();
+ } else {
+ FILE *f;
+ unsigned n = 0;
+
+ f = fopen(SYSTEMD_KBD_MODEL_MAP, "re");
+ if (!f)
+ return -errno;
+
+ for (;;) {
+ char **a;
+ int r;
+
+ r = read_next_mapping(f, &n, &a);
+ if (r < 0) {
+ fclose(f);
+ return r;
+ }
+
+ if (r == 0)
+ break;
+
+ if (!streq(vc_keymap, a[0])) {
+ strv_free(a);
+ continue;
+ }
+
+ if (!streq_ptr(x11_layout, strnulldash(a[1])) ||
+ !streq_ptr(x11_model, strnulldash(a[2])) ||
+ !streq_ptr(x11_variant, strnulldash(a[3])) ||
+ !streq_ptr(x11_options, strnulldash(a[4]))) {
+
+ if (free_and_set(&x11_layout, strnulldash(a[1])) < 0 ||
+ free_and_set(&x11_model, strnulldash(a[2])) < 0 ||
+ free_and_set(&x11_variant, strnulldash(a[3])) < 0 ||
+ free_and_set(&x11_options, strnulldash(a[4])) < 0) {
+ strv_free(a);
+ fclose(f);
+ return -ENOMEM;
+ }
+
+ modified = true;
+ }
+
+ strv_free(a);
+ break;
+ }
+
+ fclose(f);
+ }
+
+ if (modified) {
+ dbus_bool_t b;
+ DBusMessage *changed;
+ int r;
+
+ r = write_data_x11();
+ if (r < 0)
+ log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
+
+ changed = bus_properties_changed_new(
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ "X11Layout\0"
+ "X11Model\0"
+ "X11Variant\0"
+ "X11Options\0");
+
+ if (!changed)
+ return -ENOMEM;
+
+ b = dbus_connection_send(connection, changed, NULL);
+ dbus_message_unref(changed);
+
+ if (!b)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int convert_x11_to_vconsole(DBusConnection *connection) {
+ bool modified = false;
+
+ assert(connection);
+
+ if (isempty(x11_layout)) {
+
+ modified =
+ !isempty(vc_keymap) ||
+ !isempty(vc_keymap_toggle);
+
+ free_data_x11();
+ } else {
+ FILE *f;
+ unsigned n = 0;
+ unsigned best_matching = 0;
+ char *new_keymap = NULL;
+
+ f = fopen(SYSTEMD_KBD_MODEL_MAP, "re");
+ if (!f)
+ return -errno;
+
+ for (;;) {
+ char **a;
+ unsigned matching = 0;
+ int r;
+
+ r = read_next_mapping(f, &n, &a);
+ if (r < 0) {
+ fclose(f);
+ return r;
+ }
+
+ if (r == 0)
+ break;
+
+ /* Determine how well matching this entry is */
+ if (streq_ptr(x11_layout, a[1]))
+ /* If we got an exact match, this is best */
+ matching = 10;
+ else {
+ size_t x;
+
+ x = strcspn(x11_layout, ",");
+
+ /* We have multiple X layouts, look
+ * for an entry that matches our key
+ * with the everything but the first
+ * layout stripped off. */
+ if (x > 0 &&
+ strlen(a[1]) == x &&
+ strncmp(x11_layout, a[1], x) == 0)
+ matching = 5;
+ else {
+ size_t w;
+
+ /* If that didn't work, strip
+ * off the other layouts from
+ * the entry, too */
+
+ w = strcspn(a[1], ",");
+
+ if (x > 0 && x == w &&
+ memcmp(x11_layout, a[1], x) == 0)
+ matching = 1;
+ }
+ }
+
+ if (matching > 0 &&
+ streq_ptr(x11_model, a[2])) {
+ matching++;
+
+ if (streq_ptr(x11_variant, a[3])) {
+ matching++;
+
+ if (streq_ptr(x11_options, a[4]))
+ matching++;
+ }
+ }
+
+ /* The best matching entry so far, then let's
+ * save that */
+ if (matching > best_matching) {
+ best_matching = matching;
+
+ free(new_keymap);
+ new_keymap = strdup(a[0]);
+
+ if (!new_keymap) {
+ strv_free(a);
+ fclose(f);
+ return -ENOMEM;
+ }
+ }
+
+ strv_free(a);
+ }
+
+ fclose(f);
+
+ if (!streq_ptr(vc_keymap, new_keymap)) {
+ free(vc_keymap);
+ vc_keymap = new_keymap;
+
+ free(vc_keymap_toggle);
+ vc_keymap_toggle = NULL;
+
+ modified = true;
+ } else
+ free(new_keymap);
+ }
+
+ if (modified) {
+ dbus_bool_t b;
+ DBusMessage *changed;
+ int r;
+
+ r = write_data_vconsole();
+ if (r < 0)
+ log_error("Failed to set virtual console keymap: %s", strerror(-r));
+
+ changed = bus_properties_changed_new(
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ "VConsoleKeymap\0"
+ "VConsoleKeymapToggle\0");
+
+ if (!changed)
+ return -ENOMEM;
+
+ b = dbus_connection_send(connection, changed, NULL);
+ dbus_message_unref(changed);
+
+ if (!b)
+ return -ENOMEM;
+
+ return load_vconsole_keymap(connection, NULL);
+ }
+
+ return 0;
+}
+
static int append_locale(DBusMessageIter *i, const char *property, void *userdata) {
int r, c = 0, p;
char **l;
@@ -354,7 +1007,13 @@ static DBusHandlerResult locale_message_handler(
void *userdata) {
const BusProperty properties[] = {
- { "org.freedesktop.locale1", "Locale", append_locale, "as", NULL},
+ { "org.freedesktop.locale1", "Locale", append_locale, "as", NULL },
+ { "org.freedesktop.locale1", "X11Layout", bus_property_append_string, "s", x11_layout },
+ { "org.freedesktop.locale1", "X11Model", bus_property_append_string, "s", x11_model },
+ { "org.freedesktop.locale1", "X11Variant", bus_property_append_string, "s", x11_variant },
+ { "org.freedesktop.locale1", "X11Options", bus_property_append_string, "s", x11_options },
+ { "org.freedesktop.locale1", "VConsoleKeymap", bus_property_append_string, "s", vc_keymap },
+ { "org.freedesktop.locale1", "VConsoleKeymapToggle", bus_property_append_string, "s", vc_keymap_toggle },
{ NULL, NULL, NULL, NULL, NULL }
};
@@ -472,7 +1131,7 @@ static DBusHandlerResult locale_message_handler(
simplify();
- r = write_data();
+ r = write_data_locale();
if (r < 0) {
log_error("Failed to set locale: %s", strerror(-r));
return bus_send_error_reply(connection, message, NULL, r);
@@ -489,10 +1148,139 @@ static DBusHandlerResult locale_message_handler(
if (!changed)
goto oom;
}
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetVConsoleKeyboard")) {
+
+ const char *keymap, *keymap_toggle;
+ dbus_bool_t convert, interactive;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &keymap,
+ DBUS_TYPE_STRING, &keymap_toggle,
+ DBUS_TYPE_BOOLEAN, &convert,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(keymap))
+ keymap = NULL;
+
+ if (isempty(keymap_toggle))
+ keymap_toggle = NULL;
+
+ if (!streq_ptr(keymap, vc_keymap) ||
+ !streq_ptr(keymap_toggle, vc_keymap_toggle)) {
+
+ r = verify_polkit(connection, message, "org.freedesktop.locale1.set-keyboard", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ if (free_and_set(&vc_keymap, keymap) < 0 ||
+ free_and_set(&vc_keymap_toggle, keymap_toggle) < 0)
+ goto oom;
+
+ r = write_data_vconsole();
+ if (r < 0) {
+ log_error("Failed to set virtual console keymap: %s", strerror(-r));
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ log_info("Changed virtual console keymap to '%s'", strempty(vc_keymap));
+
+ r = load_vconsole_keymap(connection, NULL);
+ if (r < 0)
+ log_error("Failed to request keymap reload: %s", strerror(-r));
+
+ changed = bus_properties_changed_new(
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ "VConsoleKeymap\0"
+ "VConsoleKeymapToggle\0");
+ if (!changed)
+ goto oom;
+
+ if (convert) {
+ r = convert_vconsole_to_x11(connection);
+
+ if (r < 0)
+ log_error("Failed to convert keymap data: %s", strerror(-r));
+ }
+ }
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetX11Keyboard")) {
+
+ const char *layout, *model, *variant, *options;
+ dbus_bool_t convert, interactive;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &layout,
+ DBUS_TYPE_STRING, &model,
+ DBUS_TYPE_STRING, &variant,
+ DBUS_TYPE_STRING, &options,
+ DBUS_TYPE_BOOLEAN, &convert,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(layout))
+ layout = NULL;
+
+ if (isempty(model))
+ model = NULL;
+
+ if (isempty(variant))
+ variant = NULL;
+ if (isempty(options))
+ options = NULL;
+
+ if (!streq_ptr(layout, x11_layout) ||
+ !streq_ptr(model, x11_model) ||
+ !streq_ptr(variant, x11_variant) ||
+ !streq_ptr(options, x11_options)) {
+
+ r = verify_polkit(connection, message, "org.freedesktop.locale1.set-keyboard", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ if (free_and_set(&x11_layout, layout) < 0 ||
+ free_and_set(&x11_model, model) < 0 ||
+ free_and_set(&x11_variant, variant) < 0 ||
+ free_and_set(&x11_options, options) < 0)
+ goto oom;
+
+ r = write_data_x11();
+ if (r < 0) {
+ log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ log_info("Changed X11 keyboard layout to '%s'", strempty(x11_layout));
+
+ changed = bus_properties_changed_new(
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ "X11Layout\0"
+ "X11Model\0"
+ "X11Variant\0"
+ "X11Options\0");
+ if (!changed)
+ goto oom;
+
+ if (convert) {
+ r = convert_x11_to_vconsole(connection);
+
+ if (r < 0)
+ log_error("Failed to convert keymap data: %s", strerror(-r));
+ }
+ }
} else
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
+
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
diff --git a/src/logind-dbus.c b/src/logind-dbus.c
index b33a096f3c..0550d1bd1c 100644
--- a/src/logind-dbus.c
+++ b/src/logind-dbus.c
@@ -405,12 +405,16 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
goto fail;
}
+ seat = session->seat ? session->seat->id : "";
+ vtnr = session->vtnr;
b = dbus_message_append_args(
reply,
DBUS_TYPE_STRING, &session->id,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_STRING, &session->user->runtime_path,
DBUS_TYPE_UNIX_FD, &fifo_fd,
+ DBUS_TYPE_STRING, &seat,
+ DBUS_TYPE_UINT32, &vtnr,
DBUS_TYPE_INVALID);
free(p);
@@ -969,8 +973,11 @@ static DBusHandlerResult manager_message_handler(
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CreateSession")) {
r = bus_manager_create_session(m, message, &reply);
- if (r == -ENOMEM)
- goto oom;
+
+ /* Don't delay the work on OOM here, since it might be
+ * triggered by a low RLIMIT_NOFILE here (since we
+ * send a dupped fd to the client), and we'd rather
+ * see this fail quickly then be retried later */
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
diff --git a/src/mount.c b/src/mount.c
index 2fc799a6ed..ef953f0d0a 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -357,9 +357,11 @@ static int mount_add_fstab_links(Mount *m) {
if (mount_is_network(p)) {
target = SPECIAL_REMOTE_FS_TARGET;
- after = SPECIAL_NETWORK_TARGET;
- } else
+ after = SPECIAL_REMOTE_FS_PRE_TARGET;
+ } else {
target = SPECIAL_LOCAL_FS_TARGET;
+ after = SPECIAL_LOCAL_FS_PRE_TARGET;
+ }
if (!path_equal(m->where, "/"))
if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
diff --git a/src/org.freedesktop.locale1.policy.in b/src/org.freedesktop.locale1.policy.in
index 186d7d34c5..1ac50bf86c 100644
--- a/src/org.freedesktop.locale1.policy.in
+++ b/src/org.freedesktop.locale1.policy.in
@@ -26,4 +26,14 @@
</defaults>
</action>
+ <action id="org.freedesktop.locale1.set-keyboard">
+ <_description>Set system keyboard settings</_description>
+ <_message>Authentication is required to set the system keyboard settings.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>
diff --git a/src/pager.c b/src/pager.c
index be284da962..3fc81820e9 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -20,6 +20,7 @@
***/
#include <sys/types.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
@@ -31,6 +32,18 @@
static pid_t pager_pid = 0;
+_noreturn_ static void pager_fallback(void) {
+ ssize_t n;
+ do {
+ n = splice(STDIN_FILENO, NULL, STDOUT_FILENO, NULL, 64*1024, 0);
+ } while (n > 0);
+ if (n < 0) {
+ log_error("Internal pager failed: %m");
+ _exit(EXIT_FAILURE);
+ }
+ _exit(EXIT_SUCCESS);
+}
+
void pager_open(void) {
int fd[2];
const char *pager;
@@ -96,10 +109,9 @@ void pager_open(void) {
execlp("less", "less", NULL);
execlp("more", "more", NULL);
- execlp("cat", "cat", NULL);
- log_error("Unable to execute pager: %m");
- _exit(EXIT_FAILURE);
+ pager_fallback();
+ /* not reached */
}
/* Return in the parent */
diff --git a/src/readahead-common.h b/src/readahead-common.h
index 167df316d9..9547ad201c 100644
--- a/src/readahead-common.h
+++ b/src/readahead-common.h
@@ -27,7 +27,7 @@
#include "macro.h"
-#define READAHEAD_FILE_SIZE_MAX (128*1024*1024)
+#define READAHEAD_FILE_SIZE_MAX (10*1024*1024)
int file_verify(int fd, const char *fn, off_t file_size_max, struct stat *st);
diff --git a/src/sd-login.h b/src/sd-login.h
index 7102eb88e0..0cb0bf06bb 100644
--- a/src/sd-login.h
+++ b/src/sd-login.h
@@ -83,7 +83,7 @@ int sd_session_get_seat(const char *session, char **seat);
int sd_seat_get_active(const char *seat, char **session, uid_t *uid);
/* Return sessions and users on seat. Returns number of sessions as
- * return value. If sessions is NULL returs only the number of
+ * return value. If sessions is NULL returns only the number of
* sessions. */
int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids);
@@ -94,7 +94,7 @@ int sd_seat_can_multi_session(const char *seat);
* seats is NULL only returns number of seats. */
int sd_get_seats(char ***seats);
-/* Get all sessions, store in *seessions. Returns the number of
+/* Get all sessions, store in *sessions. Returns the number of
* sessions. If sessions is NULL only returns number of sessions. */
int sd_get_sessions(char ***sessions);
diff --git a/src/service.c b/src/service.c
index c2053ce3ac..e64d289fed 100644
--- a/src/service.c
+++ b/src/service.c
@@ -829,6 +829,7 @@ static int service_load_sysv_path(Service *s, const char *path) {
/* Special setting for all SysV services */
s->type = SERVICE_FORKING;
s->remain_after_exit = !s->pid_file;
+ s->guess_main_pid = false;
s->restart = SERVICE_RESTART_NO;
if (s->meta.manager->sysv_console)
diff --git a/src/special.h b/src/special.h
index 614e53ca1b..3fe34c955c 100644
--- a/src/special.h
+++ b/src/special.h
@@ -45,7 +45,9 @@
#define SPECIAL_SYSINIT_TARGET "sysinit.target"
#define SPECIAL_SOCKETS_TARGET "sockets.target"
#define SPECIAL_LOCAL_FS_TARGET "local-fs.target" /* LSB's $local_fs */
+#define SPECIAL_LOCAL_FS_PRE_TARGET "local-fs-pre.target"
#define SPECIAL_REMOTE_FS_TARGET "remote-fs.target" /* LSB's $remote_fs */
+#define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target"
#define SPECIAL_SWAP_TARGET "swap.target"
#define SPECIAL_BASIC_TARGET "basic.target"
diff --git a/src/systemctl.c b/src/systemctl.c
index 2bf2b697e2..0de2444d43 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -66,6 +66,7 @@ static const char *arg_job_mode = "replace";
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
static bool arg_immediate = false;
static bool arg_no_block = false;
+static bool arg_no_legend = false;
static bool arg_no_pager = false;
static bool arg_no_wtmp = false;
static bool arg_no_sync = false;
@@ -314,35 +315,60 @@ static bool output_show_unit(const struct unit_info *u) {
}
static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
- unsigned active_len, sub_len, job_len, n_shown = 0;
+ unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
const struct unit_info *u;
+ max_id_len = sizeof("UNIT")-1;
active_len = sizeof("ACTIVE")-1;
sub_len = sizeof("SUB")-1;
job_len = sizeof("JOB")-1;
+ desc_len = 0;
for (u = unit_infos; u < unit_infos + c; u++) {
if (!output_show_unit(u))
continue;
+ max_id_len = MAX(max_id_len, strlen(u->id));
active_len = MAX(active_len, strlen(u->active_state));
sub_len = MAX(sub_len, strlen(u->sub_state));
if (u->job_id != 0)
job_len = MAX(job_len, strlen(u->job_type));
}
- if (on_tty()) {
- printf("%-25s %-6s %-*s %-*s %-*s", "UNIT", "LOAD",
+ if (!arg_full) {
+ unsigned basic_len;
+ id_len = MIN(max_id_len, 25);
+ basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
+ if (basic_len < (unsigned) columns()) {
+ unsigned extra_len, incr;
+ extra_len = columns() - basic_len;
+ /* Either UNIT already got 25, or is fully satisfied.
+ * Grant up to 25 to DESC now. */
+ incr = MIN(extra_len, 25);
+ desc_len += incr;
+ extra_len -= incr;
+ /* split the remaining space between UNIT and DESC,
+ * but do not give UNIT more than it needs. */
+ if (extra_len > 0) {
+ incr = MIN(extra_len / 2, max_id_len - id_len);
+ id_len += incr;
+ desc_len += extra_len - incr;
+ }
+ }
+ } else
+ id_len = max_id_len;
+
+ if (!arg_no_legend) {
+ printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
- if (columns() >= 80+12 || arg_full || !arg_no_pager)
- printf(" %s\n", "DESCRIPTION");
+ if (!arg_full && arg_no_pager)
+ printf("%.*s\n", desc_len, "DESCRIPTION");
else
- printf("\n");
+ printf("%s\n", "DESCRIPTION");
}
for (u = unit_infos; u < unit_infos + c; u++) {
char *e;
- int a = 0, b = 0;
const char *on_loaded, *off_loaded;
const char *on_active, *off_active;
@@ -364,39 +390,23 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
} else
on_active = off_active = "";
- e = arg_full ? NULL : ellipsize(u->id, 25, 33);
+ e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
- printf("%-25s %s%-6s%s %s%-*s %-*s%s%n",
- e ? e : u->id,
+ printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
+ id_len, e ? e : u->id,
on_loaded, u->load_state, off_loaded,
on_active, active_len, u->active_state,
sub_len, u->sub_state, off_active,
- &a);
-
- free(e);
-
- a -= strlen(on_loaded) + strlen(off_loaded);
- a -= strlen(on_active) + strlen(off_active);
-
- if (u->job_id != 0)
- printf(" %-*s", job_len, u->job_type);
+ job_len, u->job_id ? u->job_type : "");
+ if (!arg_full && arg_no_pager)
+ printf("%.*s\n", desc_len, u->description);
else
- b = 1 + job_len;
+ printf("%s\n", u->description);
- if (a + b + 1 < columns()) {
- if (u->job_id == 0)
- printf(" %-*s", job_len, "");
-
- if (arg_full || !arg_no_pager)
- printf(" %s", u->description);
- else
- printf(" %.*s", columns() - a - b - 1, u->description);
- }
-
- fputs("\n", stdout);
+ free(e);
}
- if (on_tty()) {
+ if (!arg_no_legend) {
printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
"ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
"SUB = The low-level unit activation state, values depend on unit type.\n"
@@ -3924,6 +3934,7 @@ static int systemctl_help(void) {
" --no-wall Don't send wall message before halt/power-off/reboot\n"
" --no-reload When enabling/disabling unit files, don't reload daemon\n"
" configuration\n"
+ " --no-legend Do not print a legend (column headers and hints)\n"
" --no-pager Do not pipe output into a pager\n"
" --no-ask-password\n"
" Do not ask for system passwords\n"
@@ -4074,6 +4085,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_SYSTEM,
ARG_GLOBAL,
ARG_NO_BLOCK,
+ ARG_NO_LEGEND,
ARG_NO_PAGER,
ARG_NO_WALL,
ARG_ORDER,
@@ -4102,6 +4114,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "global", no_argument, NULL, ARG_GLOBAL },
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
+ { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
{ "quiet", no_argument, NULL, 'q' },
@@ -4190,6 +4203,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_no_block = true;
break;
+ case ARG_NO_LEGEND:
+ arg_no_legend = true;
+ break;
+
case ARG_NO_PAGER:
arg_no_pager = true;
break;
@@ -4976,8 +4993,17 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
return 0;
}
+ if (!bus) {
+ log_error("Failed to get D-Bus connection: %s",
+ dbus_error_is_set(error) ? error->message : "No connection to service manager.");
+ return -EIO;
+ }
+
+ } else {
+
if (!bus && !avoid_bus()) {
- log_error("Failed to get D-Bus connection: %s", error->message);
+ log_error("Failed to get D-Bus connection: %s",
+ dbus_error_is_set(error) ? error->message : "No connection to service manager.");
return -EIO;
}
}
diff --git a/src/systemd-analyze b/src/systemd-analyze
index ac6404099e..729aa05ca1 100755
--- a/src/systemd-analyze
+++ b/src/systemd-analyze
@@ -82,7 +82,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == 'time':
initrd_time, start_time, finish_time = acquire_start_time()
if initrd_time > 0:
- print "Startup finished in %lums (kernel) + %lums (initrd) + %lums (userspace) = %lums" % ( \
+ print "Startup finished in %lums (kernel) + %lums (initramfs) + %lums (userspace) = %lums" % ( \
initrd_time/1000, \
(start_time - initrd_time)/1000, \
(finish_time - start_time)/1000, \
@@ -116,7 +116,11 @@ elif sys.argv[1] == 'plot':
data = acquire_time_data()
s = sorted(data, key = lambda i: i[1])
- count = 0
+ # Account for kernel and initramfs bars if they exist
+ if initrd_time > 0:
+ count = 3
+ else:
+ count = 2
for name, ixt, aet, axt, iet in s:
@@ -130,7 +134,7 @@ elif sys.argv[1] == 'plot':
bar_space = bar_height * 0.1
# 1000px = 10s, 1px = 10ms
- width = (finish_time - start_time)/10000 + border*2
+ width = finish_time/10000 + border*2
height = count * (bar_height + bar_space) + border * 2
if width < 1000:
@@ -147,7 +151,7 @@ elif sys.argv[1] == 'plot':
context.set_line_width(1)
context.set_source_rgb(0.7, 0.7, 0.7)
- for x in range(0, max((finish_time - start_time)/10000,110), 100):
+ for x in range(0, finish_time/10000 + 100, 100):
context.move_to(x, 0)
context.line_to(x, height-border*2)
@@ -163,11 +167,30 @@ elif sys.argv[1] == 'plot':
banner = "Running on %s (%s %s) %s" % (os.uname()[1], os.uname()[2], os.uname()[3], os.uname()[4])
draw_text(context, 0, -15, banner, hcenter = 0, vcenter = 1)
- for x in range(0, max((finish_time - start_time)/10000,110), 100):
+ for x in range(0, finish_time/10000 + 100, 100):
draw_text(context, x, -5, "%lus" % (x/100), vcenter = 0, hcenter = 0)
y = 0
+ # draw boxes for kernel and initramfs boot time
+ if initrd_time > 0:
+ draw_box(context, 0, y, initrd_time/10000, bar_height, 0.7, 0.7, 0.7)
+ draw_text(context, 10, y + bar_height/2, "kernel", hcenter = 0)
+ y += bar_height + bar_space
+
+ draw_box(context, initrd_time/10000, y, start_time/10000-initrd_time/10000, bar_height, 0.7, 0.7, 0.7)
+ draw_text(context, initrd_time/10000 + 10, y + bar_height/2, "initramfs", hcenter = 0)
+ y += bar_height + bar_space
+
+ else:
+ draw_box(context, 0, y, start_time/10000, bar_height, 0.6, 0.6, 0.6)
+ draw_text(context, 10, y + bar_height/2, "kernel", hcenter = 0)
+ y += bar_height + bar_space
+
+ draw_box(context, start_time/10000, y, finish_time/10000-start_time/10000, bar_height, 0.7, 0.7, 0.7)
+ draw_text(context, start_time/10000 + 10, y + bar_height/2, "userspace", hcenter = 0)
+ y += bar_height + bar_space
+
for name, ixt, aet, axt, iet in s:
drawn = False
@@ -176,7 +199,7 @@ elif sys.argv[1] == 'plot':
if ixt >= start_time and ixt <= finish_time:
# Activating
- a = ixt - start_time
+ a = ixt
b = min(filter(lambda x: x >= ixt, (aet, axt, iet, finish_time))) - ixt
draw_box(context, a/10000, y, b/10000, bar_height, 1, 0, 0)
@@ -188,7 +211,7 @@ elif sys.argv[1] == 'plot':
if aet >= start_time and aet <= finish_time:
# Active
- a = aet - start_time
+ a = aet
b = min(filter(lambda x: x >= aet, (axt, iet, finish_time))) - aet
draw_box(context, a/10000, y, b/10000, bar_height, .8, .6, .6)
@@ -200,7 +223,7 @@ elif sys.argv[1] == 'plot':
if axt >= start_time and axt <= finish_time:
# Deactivating
- a = axt - start_time
+ a = axt
b = min(filter(lambda x: x >= axt, (iet, finish_time))) - axt
draw_box(context, a/10000, y, b/10000, bar_height, .6, .4, .4)
@@ -222,7 +245,7 @@ elif sys.argv[1] == 'plot':
draw_text(context, 0, height-border*2, "Legend: Red = Activating; Pink = Active; Dark Pink = Deactivating", hcenter = 0, vcenter = -1)
if initrd_time > 0:
- draw_text(context, 0, height-border*2 + bar_height, "Startup finished in %lums (kernel) + %lums (initrd) + %lums (userspace) = %lums" % ( \
+ draw_text(context, 0, height-border*2 + bar_height, "Startup finished in %lums (kernel) + %lums (initramfs) + %lums (userspace) = %lums" % ( \
initrd_time/1000, \
(start_time - initrd_time)/1000, \
(finish_time - start_time)/1000, \
diff --git a/src/timedated.c b/src/timedated.c
index f6fe2d83b6..16f54b59d2 100644
--- a/src/timedated.c
+++ b/src/timedated.c
@@ -170,8 +170,24 @@ static int read_data(void) {
free_data();
r = read_one_line_file("/etc/timezone", &zone);
- if (r < 0 && r != -ENOENT)
- return r;
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_warning("Failed to read /etc/timezone: %s", strerror(-r));
+
+#ifdef TARGET_FEDORA
+ r = parse_env_file("/etc/sysconfig/clock", NEWLINE,
+ "ZONE", &zone,
+ NULL);
+
+ if (r < 0 && r != -ENOENT)
+ log_warning("Failed to read /etc/sysconfig/clock: %s", strerror(-r));
+#endif
+ }
+
+ if (isempty(zone)) {
+ free(zone);
+ zone = NULL;
+ }
verify_timezone();
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index a6b8f859aa..21bf44d3a4 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -157,6 +157,7 @@ static void load_unix_sockets(void) {
}
}
+ fclose(f);
return;
fail:
diff --git a/src/util.c b/src/util.c
index 425a732344..e46606dabb 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2307,8 +2307,10 @@ int chvt(int vt) {
0
};
- if (ioctl(fd, TIOCLINUX, tiocl) < 0)
- return -errno;
+ if (ioctl(fd, TIOCLINUX, tiocl) < 0) {
+ r = -errno;
+ goto fail;
+ }
vt = tiocl[0] <= 0 ? 1 : tiocl[0];
}
@@ -2316,7 +2318,8 @@ int chvt(int vt) {
if (ioctl(fd, VT_ACTIVATE, vt) < 0)
r = -errno;
- close_nointr_nofail(r);
+fail:
+ close_nointr_nofail(fd);
return r;
}
@@ -5682,3 +5685,21 @@ bool kexec_loaded(void) {
}
return loaded;
}
+
+int strdup_or_null(const char *a, char **b) {
+ char *c;
+
+ assert(b);
+
+ if (!a) {
+ *b = NULL;
+ return 0;
+ }
+
+ c = strdup(a);
+ if (!c)
+ return -ENOMEM;
+
+ *b = c;
+ return 0;
+}
diff --git a/src/util.h b/src/util.h
index ba0800dc07..ccbe8a3efa 100644
--- a/src/util.h
+++ b/src/util.h
@@ -467,6 +467,8 @@ int block_get_whole_disk(dev_t d, dev_t *ret);
int file_is_sticky(const char *p);
+int strdup_or_null(const char *a, char **b);
+
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
diff --git a/src/vconsole-setup.c b/src/vconsole-setup.c
index 8a89358a2d..c5f3628c9b 100644
--- a/src/vconsole-setup.c
+++ b/src/vconsole-setup.c
@@ -203,10 +203,6 @@ int main(int argc, char **argv) {
if (detect_container(NULL) <= 0)
if ((r = parse_env_file("/proc/cmdline", WHITESPACE,
-#if defined(TARGET_FEDORA) || defined(TARGET_MEEGO)
- "SYSFONT", &vc_font,
- "KEYTABLE", &vc_keymap,
-#endif
"vconsole.keymap", &vc_keymap,
"vconsole.keymap.toggle", &vc_keymap_toggle,
"vconsole.font", &vc_font,
diff --git a/units/local-fs-pre.target b/units/local-fs-pre.target
new file mode 100644
index 0000000000..11e67bac1c
--- /dev/null
+++ b/units/local-fs-pre.target
@@ -0,0 +1,11 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Local File Systems (Pre)
diff --git a/units/remote-fs-pre.target b/units/remote-fs-pre.target
new file mode 100644
index 0000000000..5406aa22d3
--- /dev/null
+++ b/units/remote-fs-pre.target
@@ -0,0 +1,15 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Remote File Systems (Pre)
+After=network.target
+
+[Install]
+WantedBy=multi-user.target
diff --git a/units/remount-rootfs.service b/units/remount-rootfs.service
index e95023f03d..89a16c8b26 100644
--- a/units/remount-rootfs.service
+++ b/units/remount-rootfs.service
@@ -10,7 +10,8 @@ Description=Remount Root FS
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service fsck-root.service
-Before=local-fs.target shutdown.target
+Before=local-fs-pre.target local-fs.target shutdown.target
+Wants=local-fs-pre.target
[Service]
Type=oneshot
diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in
index 82a2c6a0ca..4241b8b320 100644
--- a/units/systemd-logind.service.in
+++ b/units/systemd-logind.service.in
@@ -16,3 +16,7 @@ Type=dbus
BusName=org.freedesktop.login1
CapabilityBoundingSet=CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER
StandardOutput=syslog
+
+# Increase the default a bit in order to allow many simultaneous
+# logins since we keep one fd open per session.
+LimitNOFILE=16384
diff --git a/units/systemd-remount-api-vfs.service.in b/units/systemd-remount-api-vfs.service.in
index 2ccbe23c8c..6339ee64a6 100644
--- a/units/systemd-remount-api-vfs.service.in
+++ b/units/systemd-remount-api-vfs.service.in
@@ -10,7 +10,8 @@ Description=Remount API VFS
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service
-Before=local-fs.target shutdown.target
+Before=local-fs-pre.target local-fs.target shutdown.target
+Wants=local-fs-pre.target
[Service]
Type=oneshot
diff --git a/units/systemd-stdout-syslog-bridge.service.in b/units/systemd-stdout-syslog-bridge.service.in
index 23a5137068..4626145476 100644
--- a/units/systemd-stdout-syslog-bridge.service.in
+++ b/units/systemd-stdout-syslog-bridge.service.in
@@ -18,3 +18,7 @@ ExecStart=@rootlibexecdir@/systemd-stdout-syslog-bridge
NotifyAccess=all
StandardOutput=null
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_SETUID CAP_SETGID
+
+# Increase the default a bit in order to allow many simultaneous
+# services being run since we keep one fd open per service.
+LimitNOFILE=16384