diff options
author | Tollef Fog Heen <tfheen@err.no> | 2011-10-12 08:40:18 +0200 |
---|---|---|
committer | Tollef Fog Heen <tfheen@err.no> | 2011-10-12 08:40:18 +0200 |
commit | 9f539f05b7b9f6ec57e0a195b550a4ed514a1354 (patch) | |
tree | 47bb694f6c54a05b9d03b26b935c096fd2b377ca | |
parent | baf8bb13719693fbc4be438dd3c358f2f9d861cd (diff) | |
parent | d2134abdd5a21bb7e4b307f403d890901628fcf9 (diff) | |
download | systemd-9f539f05b7b9f6ec57e0a195b550a4ed514a1354.tar.gz |
Merge commit 'v37'
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 @@ -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> @@ -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 |