diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-12-17 03:11:52 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-12-17 03:11:52 -0500 |
commit | b849891b5dde5ee14ab8b7b7db74e65a4a38d993 (patch) | |
tree | 29bb0e6fda9b4b170041913de495da057bbe3621 /src/grp-initprogs | |
parent | 004efebf9cc559ea131bb9460ee0ee198e2d5da7 (diff) | |
parent | 881228ff72434a0e3401a16bd87f179ef0ab1619 (diff) |
Merge branch 'notsystemd/postmove' into notsystemd/master
# Conflicts:
# src/grp-journal/libjournal-core/.gitignore
# src/grp-system/libcore/include/core/mount.h
Diffstat (limited to 'src/grp-initprogs')
20 files changed, 384 insertions, 334 deletions
diff --git a/src/grp-initprogs/grp-sleep/systemd-hibernate-resume-generator/hibernate-resume-generator.c b/src/grp-initprogs/grp-sleep/systemd-hibernate-resume-generator/hibernate-resume-generator.c index 6774df21c5..de440853db 100644 --- a/src/grp-initprogs/grp-sleep/systemd-hibernate-resume-generator/hibernate-resume-generator.c +++ b/src/grp-initprogs/grp-sleep/systemd-hibernate-resume-generator/hibernate-resume-generator.c @@ -33,7 +33,7 @@ static const char *arg_dest = "/tmp"; static char *arg_resume_dev = NULL; -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { if (streq(key, "resume") && value) { free(arg_resume_dev); @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { if (!in_initrd()) return EXIT_SUCCESS; - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/grp-initprogs/systemd-backlight/backlight.c b/src/grp-initprogs/systemd-backlight/backlight.c index 3fd47ad611..f5b80c395e 100644 --- a/src/grp-initprogs/systemd-backlight/backlight.c +++ b/src/grp-initprogs/systemd-backlight/backlight.c @@ -167,7 +167,7 @@ static bool validate_device(struct udev *udev, struct udev_device *device) { continue; v = udev_device_get_sysattr_value(other, "type"); - if (!streq_ptr(v, "platform") && !streq_ptr(v, "firmware")) + if (!STRPTR_IN_SET(v, "platform", "firmware")) continue; /* OK, so there's another backlight device, and it's a diff --git a/src/grp-initprogs/systemd-detect-virt/detect-virt.c b/src/grp-initprogs/systemd-detect-virt/detect-virt.c index 80f4f72fab..484f689c4c 100644 --- a/src/grp-initprogs/systemd-detect-virt/detect-virt.c +++ b/src/grp-initprogs/systemd-detect-virt/detect-virt.c @@ -31,6 +31,7 @@ static enum { ONLY_VM, ONLY_CONTAINER, ONLY_CHROOT, + ONLY_PRIVATE_USERS, } arg_mode = ANY_VIRTUALIZATION; static void help(void) { @@ -41,6 +42,7 @@ static void help(void) { " -c --container Only detect whether we are run in a container\n" " -v --vm Only detect whether we are run in a VM\n" " -r --chroot Detect whether we are run in a chroot() environment\n" + " --private-users Only detect whether we are running in a user namespace\n" " -q --quiet Don't output anything, just set return value\n" , program_invocation_short_name); } @@ -48,16 +50,18 @@ static void help(void) { static int parse_argv(int argc, char *argv[]) { enum { - ARG_VERSION = 0x100 + ARG_VERSION = 0x100, + ARG_PRIVATE_USERS, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "container", no_argument, NULL, 'c' }, - { "vm", no_argument, NULL, 'v' }, - { "chroot", no_argument, NULL, 'r' }, - { "quiet", no_argument, NULL, 'q' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "container", no_argument, NULL, 'c' }, + { "vm", no_argument, NULL, 'v' }, + { "chroot", no_argument, NULL, 'r' }, + { "private-users", no_argument, NULL, ARG_PRIVATE_USERS }, + { "quiet", no_argument, NULL, 'q' }, {} }; @@ -85,6 +89,10 @@ static int parse_argv(int argc, char *argv[]) { arg_mode = ONLY_CONTAINER; break; + case ARG_PRIVATE_USERS: + arg_mode = ONLY_PRIVATE_USERS; + break; + case 'v': arg_mode = ONLY_VM; break; @@ -151,6 +159,15 @@ int main(int argc, char *argv[]) { return r ? EXIT_SUCCESS : EXIT_FAILURE; + case ONLY_PRIVATE_USERS: + r = running_in_userns(); + if (r < 0) { + log_error_errno(r, "Failed to check for user namespace: %m"); + return EXIT_FAILURE; + } + + return r ? EXIT_SUCCESS : EXIT_FAILURE; + case ANY_VIRTUALIZATION: default: r = detect_virtualization(); diff --git a/src/grp-initprogs/systemd-detect-virt/systemd-detect-virt.xml b/src/grp-initprogs/systemd-detect-virt/systemd-detect-virt.xml index 2b7f4e69ab..996c2fa256 100644 --- a/src/grp-initprogs/systemd-detect-virt/systemd-detect-virt.xml +++ b/src/grp-initprogs/systemd-detect-virt/systemd-detect-virt.xml @@ -50,7 +50,8 @@ <refsynopsisdiv> <cmdsynopsis> - <command>systemd-detect-virt <arg choice="opt" rep="repeat">OPTIONS</arg></command> + <command>systemd-detect-virt</command> + <arg choice="opt" rep="repeat">OPTIONS</arg> </cmdsynopsis> </refsynopsisdiv> @@ -88,7 +89,7 @@ </thead> <tbody> <row> - <entry valign="top" morerows="9">VM</entry> + <entry valign="top" morerows="10">VM</entry> <entry><varname>qemu</varname></entry> <entry>QEMU software virtualization</entry> </row> @@ -138,6 +139,11 @@ <entry>Parallels Desktop, Parallels Server</entry> </row> + <row> + <entry><varname>bhyve</varname></entry> + <entry>bhyve, FreeBSD hypervisor</entry> + </row> + <row> <entry valign="top" morerows="5">Container</entry> <entry><varname>openvz</varname></entry> @@ -213,6 +219,16 @@ </varlistentry> <varlistentry> + <term><option>--private-users</option></term> + + <listitem><para>Detect whether invoked in a user namespace. In this mode, no + output is written, but the return value indicates whether the process was invoked + inside of a user namespace or not. See + <citerefentry project='man-pages'><refentrytitle>user_namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry> + for more information.</para></listitem> + </varlistentry> + + <varlistentry> <term><option>-q</option></term> <term><option>--quiet</option></term> @@ -238,7 +254,8 @@ <para> <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>, - <citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry> + <citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry>, + <citerefentry project='man-pages'><refentrytitle>namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry> </para> </refsect1> diff --git a/src/grp-initprogs/systemd-fsck/fsck.c b/src/grp-initprogs/systemd-fsck/fsck.c index c33d199ef5..df6f96096b 100644 --- a/src/grp-initprogs/systemd-fsck/fsck.c +++ b/src/grp-initprogs/systemd-fsck/fsck.c @@ -94,7 +94,7 @@ static void start_target(const char *target, const char *mode) { log_error("Failed to start unit: %s", bus_error_message(&error, r)); } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; assert(key); @@ -293,7 +293,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/grp-initprogs/systemd-modules-load/modules-load.c b/src/grp-initprogs/systemd-modules-load/modules-load.c index 13f6ac529d..077561e2ba 100644 --- a/src/grp-initprogs/systemd-modules-load/modules-load.c +++ b/src/grp-initprogs/systemd-modules-load/modules-load.c @@ -59,10 +59,10 @@ static int add_modules(const char *p) { return 0; } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; - if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) { + if (streq(key, "modules-load") && value) { r = add_modules(value); if (r < 0) return r; @@ -226,7 +226,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/grp-initprogs/systemd-quotacheck/quotacheck.c b/src/grp-initprogs/systemd-quotacheck/quotacheck.c index eadd78c9da..7687354ad6 100644 --- a/src/grp-initprogs/systemd-quotacheck/quotacheck.c +++ b/src/grp-initprogs/systemd-quotacheck/quotacheck.c @@ -32,7 +32,7 @@ static bool arg_skip = false; static bool arg_force = false; -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { if (streq(key, "quotacheck.mode") && value) { @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/grp-initprogs/systemd-random-seed/systemd-random-seed.service.in b/src/grp-initprogs/systemd-random-seed/systemd-random-seed.service.in index 115233268d..b244a8ce43 100644 --- a/src/grp-initprogs/systemd-random-seed/systemd-random-seed.service.in +++ b/src/grp-initprogs/systemd-random-seed/systemd-random-seed.service.in @@ -13,6 +13,7 @@ RequiresMountsFor=@RANDOM_SEED@ Conflicts=shutdown.target After=systemd-remount-fs.service Before=sysinit.target shutdown.target +ConditionVirtualization=!container [Service] Type=oneshot diff --git a/src/grp-initprogs/systemd-sysctl/sysctl.c b/src/grp-initprogs/systemd-sysctl/sysctl.c index c5d666904d..de047890f6 100644 --- a/src/grp-initprogs/systemd-sysctl/sysctl.c +++ b/src/grp-initprogs/systemd-sysctl/sysctl.c @@ -41,29 +41,56 @@ static char **arg_prefixes = NULL; static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d"); -static int apply_all(Hashmap *sysctl_options) { +static int apply_all(OrderedHashmap *sysctl_options) { char *property, *value; Iterator i; int r = 0; - HASHMAP_FOREACH_KEY(value, property, sysctl_options, i) { + ORDERED_HASHMAP_FOREACH_KEY(value, property, sysctl_options, i) { int k; k = sysctl_write(property, value); if (k < 0) { - log_full_errno(k == -ENOENT ? LOG_INFO : LOG_WARNING, k, - "Couldn't write '%s' to '%s', ignoring: %m", value, property); - - if (r == 0 && k != -ENOENT) - r = k; + /* If the sysctl is not available in the kernel or we are running with reduced privileges and + * cannot write it, then log about the issue at LOG_NOTICE level, and proceed without + * failing. (EROFS is treated as a permission problem here, since that's how container managers + * usually protected their sysctls.) In all other cases log an error and make the tool fail. */ + + if (IN_SET(k, -EPERM, -EACCES, -EROFS, -ENOENT)) + log_notice_errno(k, "Couldn't write '%s' to '%s', ignoring: %m", value, property); + else { + log_error_errno(k, "Couldn't write '%s' to '%s': %m", value, property); + if (r == 0) + r = k; + } } } return r; } -static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_enoent) { +static bool test_prefix(const char *p) { + char **i; + + if (strv_isempty(arg_prefixes)) + return true; + + STRV_FOREACH(i, arg_prefixes) { + const char *t; + + t = path_startswith(*i, "/proc/sys/"); + if (!t) + t = *i; + if (path_startswith(p, t)) + return true; + } + + return false; +} + +static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; + unsigned c = 0; int r; assert(path); @@ -77,7 +104,7 @@ static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_eno } log_debug("Parsing %s", path); - while (!feof(f)) { + for (;;) { char l[LINE_MAX], *p, *value, *new_value, *property, *existing; void *v; int k; @@ -89,6 +116,8 @@ static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_eno return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path); } + c++; + p = strstrip(l); if (!*p) continue; @@ -98,7 +127,7 @@ static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_eno value = strchr(p, '='); if (!value) { - log_error("Line is not an assignment in file '%s': %s", path, value); + log_error("Line is not an assignment at '%s:%u': %s", path, c, value); if (r == 0) r = -EINVAL; @@ -111,27 +140,16 @@ static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_eno p = sysctl_normalize(strstrip(p)); value = strstrip(value); - if (!strv_isempty(arg_prefixes)) { - char **i, *t; - STRV_FOREACH(i, arg_prefixes) { - t = path_startswith(*i, "/proc/sys/"); - if (t == NULL) - t = *i; - if (path_startswith(p, t)) - goto found; - } - /* not found */ + if (!test_prefix(p)) continue; - } -found: - existing = hashmap_get2(sysctl_options, p, &v); + existing = ordered_hashmap_get2(sysctl_options, p, &v); if (existing) { if (streq(value, existing)) continue; - log_debug("Overwriting earlier assignment of %s in file '%s'.", p, path); - free(hashmap_remove(sysctl_options, p)); + log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, path, c); + free(ordered_hashmap_remove(sysctl_options, p)); free(v); } @@ -145,7 +163,7 @@ found: return log_oom(); } - k = hashmap_put(sysctl_options, property, new_value); + k = ordered_hashmap_put(sysctl_options, property, new_value); if (k < 0) { log_error_errno(k, "Failed to add sysctl variable %s to hashmap: %m", property); free(property); @@ -229,12 +247,12 @@ static int parse_argv(int argc, char *argv[]) { } int main(int argc, char *argv[]) { + OrderedHashmap *sysctl_options = NULL; int r = 0, k; - Hashmap *sysctl_options; r = parse_argv(argc, argv); if (r <= 0) - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + goto finish; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); @@ -242,7 +260,7 @@ int main(int argc, char *argv[]) { umask(0022); - sysctl_options = hashmap_new(&string_hash_ops); + sysctl_options = ordered_hashmap_new(&string_hash_ops); if (!sysctl_options) { r = log_oom(); goto finish; @@ -280,7 +298,7 @@ int main(int argc, char *argv[]) { r = k; finish: - hashmap_free_free_free(sysctl_options); + ordered_hashmap_free_free_free(sysctl_options); strv_free(arg_prefixes); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; diff --git a/src/grp-initprogs/systemd-sysctl/systemd-sysctl.service.in b/src/grp-initprogs/systemd-sysctl/systemd-sysctl.service.in index d784c6426d..980f611df2 100644 --- a/src/grp-initprogs/systemd-sysctl/systemd-sysctl.service.in +++ b/src/grp-initprogs/systemd-sysctl/systemd-sysctl.service.in @@ -12,7 +12,7 @@ DefaultDependencies=no Conflicts=shutdown.target After=systemd-modules-load.service Before=sysinit.target shutdown.target -ConditionPathIsReadWrite=/proc/sys/ +ConditionPathIsReadWrite=/proc/sys/net/ [Service] Type=oneshot diff --git a/src/grp-initprogs/systemd-sysusers/sysusers.c b/src/grp-initprogs/systemd-sysusers/sysusers.c index 020ddbdf5e..fc1ae6df3a 100644 --- a/src/grp-initprogs/systemd-sysusers/sysusers.c +++ b/src/grp-initprogs/systemd-sysusers/sysusers.c @@ -190,7 +190,8 @@ static int load_group_database(void) { static int make_backup(const char *target, const char *x) { _cleanup_close_ int src = -1; _cleanup_fclose_ FILE *dst = NULL; - char *backup, *temp; + _cleanup_free_ char *temp = NULL; + char *backup; struct timespec ts[2]; struct stat st; int r; @@ -1189,6 +1190,7 @@ static void item_free(Item *i) { free(i->uid_path); free(i->gid_path); free(i->description); + free(i->home); free(i); } @@ -1299,81 +1301,6 @@ static bool item_equal(Item *a, Item *b) { return true; } -static bool valid_user_group_name(const char *u) { - const char *i; - long sz; - - if (isempty(u)) - return false; - - if (!(u[0] >= 'a' && u[0] <= 'z') && - !(u[0] >= 'A' && u[0] <= 'Z') && - u[0] != '_') - return false; - - for (i = u+1; *i; i++) { - if (!(*i >= 'a' && *i <= 'z') && - !(*i >= 'A' && *i <= 'Z') && - !(*i >= '0' && *i <= '9') && - *i != '_' && - *i != '-') - return false; - } - - sz = sysconf(_SC_LOGIN_NAME_MAX); - assert_se(sz > 0); - - if ((size_t) (i-u) > (size_t) sz) - return false; - - if ((size_t) (i-u) > UT_NAMESIZE - 1) - return false; - - return true; -} - -static bool valid_gecos(const char *d) { - - if (!d) - return false; - - if (!utf8_is_valid(d)) - return false; - - if (string_has_cc(d, NULL)) - return false; - - /* Colons are used as field separators, and hence not OK */ - if (strchr(d, ':')) - return false; - - return true; -} - -static bool valid_home(const char *p) { - - if (isempty(p)) - return false; - - if (!utf8_is_valid(p)) - return false; - - if (string_has_cc(p, NULL)) - return false; - - if (!path_is_absolute(p)) - return false; - - if (!path_is_safe(p)) - return false; - - /* Colons are used as field separators, and hence not OK */ - if (strchr(p, ':')) - return false; - - return true; -} - static int parse_line(const char *fname, unsigned line, const char *buffer) { static const Specifier specifier_table[] = { diff --git a/src/grp-initprogs/systemd-tmpfiles/tmpfiles.d.xml b/src/grp-initprogs/systemd-tmpfiles/tmpfiles.d.xml index 957475d2bd..e040a1636d 100644 --- a/src/grp-initprogs/systemd-tmpfiles/tmpfiles.d.xml +++ b/src/grp-initprogs/systemd-tmpfiles/tmpfiles.d.xml @@ -626,7 +626,7 @@ <example> <title>Create directories with specific mode and ownership</title> <para> - <citerefentry><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>, + <citerefentry project='die-net'><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>, needs two directories created at boot with specific modes and ownership:</para> <programlisting># /usr/lib/tmpfiles.d/screen.conf @@ -644,7 +644,7 @@ d /run/uscreens 0755 root screen 10d12h t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar" </programlisting> - <para>The direcory will be owned by root and have default mode. It's contents are + <para>The directory will be owned by root and have default mode. Its contents are not subject to time based cleanup, but will be obliterated when <command>systemd-tmpfiles --remove</command> runs.</para> </example> @@ -652,7 +652,7 @@ t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar" <example> <title>Create a directory and prevent its contents from cleanup</title> <para> - <citerefentry><refentrytitle>abrt</refentrytitle><manvolnum>1</manvolnum></citerefentry>, + <citerefentry project='die-net'><refentrytitle>abrt</refentrytitle><manvolnum>1</manvolnum></citerefentry>, needs a directory created at boot with specific mode and ownership and its content should be preserved from the automatic cleanup applied to the contents of <filename>/var/tmp</filename>:</para> diff --git a/src/grp-initprogs/systemd-update-done/update-done.c b/src/grp-initprogs/systemd-update-done/update-done.c index 79f755b909..f35e293e3d 100644 --- a/src/grp-initprogs/systemd-update-done/update-done.c +++ b/src/grp-initprogs/systemd-update-done/update-done.c @@ -18,72 +18,65 @@ ***/ #include "systemd-basic/fd-util.h" +#include "systemd-basic/fileio.h" #include "systemd-basic/io-util.h" #include "systemd-basic/selinux-util.h" #include "systemd-basic/util.h" #define MESSAGE \ - "This file was created by systemd-update-done. Its only \n" \ - "purpose is to hold a timestamp of the time this directory\n" \ - "was updated. See systemd-update-done.service(8).\n" + "# This file was created by systemd-update-done. Its only \n" \ + "# purpose is to hold a timestamp of the time this directory\n" \ + "# was updated. See systemd-update-done.service(8).\n" static int apply_timestamp(const char *path, struct timespec *ts) { struct timespec twice[2] = { *ts, *ts }; - struct stat st; + _cleanup_fclose_ FILE *f = NULL; + int fd = -1; + int r; assert(path); assert(ts); - if (stat(path, &st) >= 0) { - /* Is the timestamp file already newer than the OS? If - * so, there's nothing to do. We ignore the nanosecond - * component of the timestamp, since some file systems - * do not support any better accuracy than 1s and we - * have no way to identify the accuracy - * available. Most notably ext4 on small disks (where - * 128 byte inodes are used) does not support better - * accuracy than 1s. */ - if (st.st_mtim.tv_sec > ts->tv_sec) - return 0; - - /* It is older? Then let's update it */ - if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) { - - if (errno == EROFS) - return log_debug("Can't update timestamp file %s, file system is read-only.", path); + /* + * We store the timestamp both as mtime of the file and in the file itself, + * to support filesystems which cannot store nanosecond-precision timestamps. + * Hence, don't bother updating the file, let's just rewrite it. + */ - return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); - } + r = mac_selinux_create_file_prepare(path, S_IFREG); + if (r < 0) + return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); - } else if (errno == ENOENT) { - _cleanup_close_ int fd = -1; - int r; + fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); + mac_selinux_create_file_clear(); - /* The timestamp file doesn't exist yet? Then let's create it. */ + if (fd < 0) { + if (errno == EROFS) + return log_debug("Can't create timestamp file %s, file system is read-only.", path); - r = mac_selinux_create_file_prepare(path, S_IFREG); - if (r < 0) - return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); - - fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); - mac_selinux_create_file_clear(); + return log_error_errno(errno, "Failed to create/open timestamp file %s: %m", path); + } - if (fd < 0) { - if (errno == EROFS) - return log_debug("Can't create timestamp file %s, file system is read-only.", path); + f = fdopen(fd, "we"); + if (!f) { + safe_close(fd); + return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", path); + } - return log_error_errno(errno, "Failed to create timestamp file %s: %m", path); - } + (void) fprintf(f, + MESSAGE + "TIMESTAMP_NSEC=" NSEC_FMT "\n", + timespec_load_nsec(ts)); - (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false); + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write timestamp file: %m"); - if (futimens(fd, twice) < 0) - return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); - } else - log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path); + if (futimens(fd, twice) < 0) + return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); return 0; } diff --git a/src/grp-initprogs/systemd-update-utmp/update-utmp.c b/src/grp-initprogs/systemd-update-utmp/update-utmp.c index ccb8543cfe..8f622caa64 100644 --- a/src/grp-initprogs/systemd-update-utmp/update-utmp.c +++ b/src/grp-initprogs/systemd-update-utmp/update-utmp.c @@ -34,6 +34,7 @@ #include "systemd-basic/log.h" #include "systemd-basic/macro.h" #include "systemd-basic/special.h" +#include "systemd-basic/strv.h" #include "systemd-basic/unit-name.h" #include "systemd-basic/util.h" #include "systemd-shared/utmp-wtmp.h" @@ -107,7 +108,7 @@ static int get_current_runlevel(Context *c) { if (r < 0) return log_warning_errno(r, "Failed to get state: %s", bus_error_message(&error, r)); - if (streq(state, "active") || streq(state, "reloading")) + if (STR_IN_SET(state, "active", "reloading")) return table[i].runlevel; } diff --git a/src/grp-initprogs/systemd-vconsole-setup/90-vconsole.rules.in b/src/grp-initprogs/systemd-vconsole-setup/90-vconsole.rules.in index 35b9ad5151..84b4d575bd 100644 --- a/src/grp-initprogs/systemd-vconsole-setup/90-vconsole.rules.in +++ b/src/grp-initprogs/systemd-vconsole-setup/90-vconsole.rules.in @@ -7,4 +7,4 @@ # Each vtcon keeps its own state of fonts. # -ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", RUN+="@rootlibexecdir@/systemd-vconsole-setup" +ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", ATTR{name}!="*dummy device", RUN+="@rootlibexecdir@/systemd-vconsole-setup" diff --git a/src/grp-initprogs/systemd-vconsole-setup/Makefile b/src/grp-initprogs/systemd-vconsole-setup/Makefile index 5a93ae780b..d1918d968e 100644 --- a/src/grp-initprogs/systemd-vconsole-setup/Makefile +++ b/src/grp-initprogs/systemd-vconsole-setup/Makefile @@ -38,9 +38,6 @@ nodist_udevrules_DATA += \ nodist_systemunit_DATA += \ units/systemd-vconsole-setup.service - -SYSINIT_TARGET_WANTS += \ - systemd-vconsole-setup.service endif # ENABLE_VCONSOLE EXTRA_DIST += \ diff --git a/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.in b/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.in index 6160361871..2bd1fd1a5d 100644 --- a/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.in +++ b/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.in @@ -9,11 +9,8 @@ Description=Setup Virtual Console Documentation=man:systemd-vconsole-setup.service(8) man:vconsole.conf(5) DefaultDependencies=no -Conflicts=shutdown.target -Before=sysinit.target shutdown.target ConditionPathExists=/dev/tty0 [Service] Type=oneshot -RemainAfterExit=yes ExecStart=@rootlibexecdir@/systemd-vconsole-setup diff --git a/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.xml b/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.xml index ff079761c1..f2da2a7b77 100644 --- a/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.xml +++ b/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.xml @@ -43,61 +43,39 @@ <refnamediv> <refname>systemd-vconsole-setup.service</refname> <refname>systemd-vconsole-setup</refname> - <refpurpose>Configure the virtual console at boot</refpurpose> + <refpurpose>Configure the virtual consoles</refpurpose> </refnamediv> <refsynopsisdiv> <para><filename>systemd-vconsole-setup.service</filename></para> - <para><filename>/usr/lib/systemd/systemd-vconsole-setup</filename></para> + <cmdsynopsis> + <command>/usr/lib/systemd/systemd-vconsole-setup</command> + <arg choice="opt">TTY</arg> + </cmdsynopsis> </refsynopsisdiv> <refsect1> <title>Description</title> - <para><filename>systemd-vconsole-setup.service</filename> is an - early boot service that configures the virtual console font and - console keymap. Internally it calls - <citerefentry project='mankier'><refentrytitle>loadkeys</refentrytitle><manvolnum>1</manvolnum></citerefentry> - and - <citerefentry project='die-net'><refentrytitle>setfont</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para> - - <para>See - <citerefentry><refentrytitle>vconsole.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> - for information about the configuration files understood by this - service.</para> - - - </refsect1> - - <refsect1> - <title>Kernel Command Line</title> - - <para>A few configuration parameters from - <filename>vconsole.conf</filename> may be overridden on the kernel - command line:</para> - - <variablelist class='kernel-commandline-options'> - <varlistentry> - <term><varname>vconsole.keymap=</varname></term> - <term><varname>vconsole.keymap.toggle=</varname></term> - - <listitem><para>Overrides the key mapping table for the - keyboard and the second toggle keymap.</para></listitem> - </varlistentry> - <varlistentry> - - <term><varname>vconsole.font=</varname></term> - <term><varname>vconsole.font.map=</varname></term> - <term><varname>vconsole.font.unimap=</varname></term> + <para><filename>systemd-vconsole-setup</filename> is a helper used to prepare either all virtual consoles, or — if + the optional <replaceable>TTY</replaceable> parameter is provided — a specific one. When the system is booting up + it's called by <citerefentry><command>udev</command></citerefentry> during vtconsole subsystem initialization. + <productname>Systemd</productname> also calls it internally as needed via + <filename>systemd-vconsole-setup.service</filename>. The helper calls + <citerefentry project='mankier'><refentrytitle>loadkeys</refentrytitle><manvolnum>1</manvolnum></citerefentry> and + <citerefentry project='die-net'><refentrytitle>setfont</refentrytitle><manvolnum>8</manvolnum></citerefentry> + internally. + </para> - <listitem><para>Configures the console font, the console map, - and the unicode font map.</para></listitem> - </varlistentry> - </variablelist> + <para> + You may want to use this helper whenever you change <filename>vconsole.conf</filename> to + refresh the settings on your consoles — either through the <command>systemctl restart</command> / + <command>systemctl start</command> command or directly through the executable. + </para> <para>See <citerefentry><refentrytitle>vconsole.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> - for information about these settings.</para> + for information about the configuration files and kernel command line options understood by this program.</para> </refsect1> <refsect1> diff --git a/src/grp-initprogs/systemd-vconsole-setup/vconsole-setup.c b/src/grp-initprogs/systemd-vconsole-setup/vconsole-setup.c index 7edab74051..ad6a4283fc 100644 --- a/src/grp-initprogs/systemd-vconsole-setup/vconsole-setup.c +++ b/src/grp-initprogs/systemd-vconsole-setup/vconsole-setup.c @@ -2,6 +2,7 @@ This file is part of systemd. Copyright 2010 Kay Sievers + Copyright 2016 Michal Soltys <soltys@ziu.info> systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -24,6 +25,7 @@ #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> +#include <termios.h> #include <unistd.h> #include <linux/kd.h> @@ -51,67 +53,85 @@ static bool is_vconsole(int fd) { return ioctl(fd, TIOCLINUX, data) >= 0; } -static int disable_utf8(int fd) { - int r = 0, k; +static bool is_allocated(unsigned int idx) { + char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)]; - if (ioctl(fd, KDSKBMODE, K_XLATE) < 0) - r = -errno; - - k = loop_write(fd, "\033%@", 3, false); - if (k < 0) - r = k; + xsprintf(vcname, "/dev/vcs%i", idx); + return access(vcname, F_OK) == 0; +} - k = write_string_file("/sys/module/vt/parameters/default_utf8", "0", 0); - if (k < 0) - r = k; +static bool is_allocated_byfd(int fd) { + struct vt_stat vcs = {}; - if (r < 0) - log_warning_errno(r, "Failed to disable UTF-8: %m"); + if (ioctl(fd, VT_GETSTATE, &vcs) < 0) { + log_warning_errno(errno, "VT_GETSTATE failed: %m"); + return false; + } + return is_allocated(vcs.v_active); +} - return r; +static bool is_settable(int fd) { + int r, curr_mode; + + r = ioctl(fd, KDGKBMODE, &curr_mode); + /* + * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode. + * Otherwise we would (likely) interfere with X11's processing of the + * key events. + * + * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html + */ + return r == 0 && IN_SET(curr_mode, K_XLATE, K_UNICODE); } -static int enable_utf8(int fd) { - int r = 0, k; - long current = 0; - - if (ioctl(fd, KDGKBMODE, ¤t) < 0 || current == K_XLATE) { - /* - * Change the current keyboard to unicode, unless it - * is currently in raw or off mode anyway. We - * shouldn't interfere with X11's processing of the - * key events. - * - * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html - * - */ - - if (ioctl(fd, KDSKBMODE, K_UNICODE) < 0) - r = -errno; +static int toggle_utf8(const char *name, int fd, bool utf8) { + int r; + struct termios tc = {}; + + assert(name); + + r = ioctl(fd, KDSKBMODE, utf8 ? K_UNICODE : K_XLATE); + if (r < 0) + return log_warning_errno(errno, "Failed to %s UTF-8 kbdmode on %s: %m", enable_disable(utf8), name); + + r = loop_write(fd, utf8 ? "\033%G" : "\033%@", 3, false); + if (r < 0) + return log_warning_errno(r, "Failed to %s UTF-8 term processing on %s: %m", enable_disable(utf8), name); + + r = tcgetattr(fd, &tc); + if (r >= 0) { + if (utf8) + tc.c_iflag |= IUTF8; + else + tc.c_iflag &= ~IUTF8; + r = tcsetattr(fd, TCSANOW, &tc); } + if (r < 0) + return log_warning_errno(errno, "Failed to %s iutf8 flag on %s: %m", enable_disable(utf8), name); - k = loop_write(fd, "\033%G", 3, false); - if (k < 0) - r = k; + log_debug("UTF-8 kbdmode %sd on %s", enable_disable(utf8), name); + return 0; +} - k = write_string_file("/sys/module/vt/parameters/default_utf8", "1", 0); - if (k < 0) - r = k; +static int toggle_utf8_sysfs(bool utf8) { + int r; + r = write_string_file("/sys/module/vt/parameters/default_utf8", one_zero(utf8), 0); if (r < 0) - log_warning_errno(r, "Failed to enable UTF-8: %m"); + return log_warning_errno(r, "Failed to %s sysfs UTF-8 flag: %m", enable_disable(utf8)); - return r; + log_debug("Sysfs UTF-8 flag %sd", enable_disable(utf8)); + return 0; } static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) { const char *args[8]; - int i = 0, r; + int i = 0; pid_t pid; /* An empty map means kernel map */ if (isempty(map)) - return 1; + return 0; args[i++] = KBD_LOADKEYS; args[i++] = "-q"; @@ -136,34 +156,31 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m _exit(EXIT_FAILURE); } - r = wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true); - if (r < 0) - return r; - - return r == 0; + return wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true); } static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) { const char *args[9]; - int i = 0, r; + int i = 0; pid_t pid; - /* An empty font means kernel font */ - if (isempty(font)) - return 1; + /* Any part can be set independently */ + if (isempty(font) && isempty(map) && isempty(unimap)) + return 0; args[i++] = KBD_SETFONT; args[i++] = "-C"; args[i++] = vc; - args[i++] = font; - if (map) { + if (!isempty(map)) { args[i++] = "-m"; args[i++] = map; } - if (unimap) { + if (!isempty(unimap)) { args[i++] = "-u"; args[i++] = unimap; } + if (!isempty(font)) + args[i++] = font; args[i++] = NULL; pid = fork(); @@ -178,11 +195,7 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map, _exit(EXIT_FAILURE); } - r = wait_for_terminate_and_warn(KBD_SETFONT, pid, true); - if (r < 0) - return r; - - return r == 0; + return wait_for_terminate_and_warn(KBD_SETFONT, pid, true); } /* @@ -190,13 +203,21 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map, * we update all possibly already allocated VTs with the configured * font. It also allows to restart systemd-vconsole-setup.service, * to apply a new font to all VTs. + * + * We also setup per-console utf8 related stuff: kbdmode, term + * processing, stty iutf8. */ -static void font_copy_to_all_vcs(int fd) { +static void setup_remaining_vcs(int fd, bool utf8) { + struct console_font_op cfo = { + .op = KD_FONT_OP_GET, + .width = UINT_MAX, .height = UINT_MAX, + .charcount = UINT_MAX, + }; struct vt_stat vcs = {}; - unsigned char map8[E_TABSZ]; - unsigned short map16[E_TABSZ]; + struct unimapinit adv = {}; struct unimapdesc unimapd; _cleanup_free_ struct unipair* unipairs = NULL; + _cleanup_free_ void *fontbuf = NULL; int i, r; unipairs = new(struct unipair, USHRT_MAX); @@ -208,52 +229,96 @@ static void font_copy_to_all_vcs(int fd) { /* get active, and 16 bit mask of used VT numbers */ r = ioctl(fd, VT_GETSTATE, &vcs); if (r < 0) { - log_debug_errno(errno, "VT_GETSTATE failed, ignoring: %m"); + log_warning_errno(errno, "VT_GETSTATE failed, ignoring remaining consoles: %m"); return; } - for (i = 1; i <= 15; i++) { - char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)]; - _cleanup_close_ int vcfd = -1; - struct console_font_op cfo = {}; + /* get metadata of the current font (width, height, count) */ + r = ioctl(fd, KDFONTOP, &cfo); + if (r < 0) + log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to get the font metadata: %m"); + else { + /* verify parameter sanity first */ + if (cfo.width > 32 || cfo.height > 32 || cfo.charcount > 512) + log_warning("Invalid font metadata - width: %u (max 32), height: %u (max 32), count: %u (max 512)", + cfo.width, cfo.height, cfo.charcount); + else { + /* + * Console fonts supported by the kernel are limited in size to 32 x 32 and maximum 512 + * characters. Thus with 1 bit per pixel it requires up to 65536 bytes. The height always + * requries 32 per glyph, regardless of the actual height - see the comment above #define + * max_font_size 65536 in drivers/tty/vt/vt.c for more details. + */ + fontbuf = malloc((cfo.width + 7) / 8 * 32 * cfo.charcount); + if (!fontbuf) { + log_oom(); + return; + } + /* get fonts from source console */ + cfo.data = fontbuf; + r = ioctl(fd, KDFONTOP, &cfo); + if (r < 0) + log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to read the font data: %m"); + else { + unimapd.entries = unipairs; + unimapd.entry_ct = USHRT_MAX; + r = ioctl(fd, GIO_UNIMAP, &unimapd); + if (r < 0) + log_warning_errno(errno, "GIO_UNIMAP failed while trying to read unicode mappings: %m"); + else + cfo.op = KD_FONT_OP_SET; + } + } + } + + if (cfo.op != KD_FONT_OP_SET) + log_warning("Fonts will not be copied to remaining consoles"); + + for (i = 1; i <= 63; i++) { + char ttyname[strlen("/dev/tty") + DECIMAL_STR_MAX(int)]; + _cleanup_close_ int fd_d = -1; - if (i == vcs.v_active) + if (i == vcs.v_active || !is_allocated(i)) continue; - /* skip non-allocated ttys */ - xsprintf(vcname, "/dev/vcs%i", i); - if (access(vcname, F_OK) < 0) + /* try to open terminal */ + xsprintf(ttyname, "/dev/tty%i", i); + fd_d = open_terminal(ttyname, O_RDWR|O_CLOEXEC); + if (fd_d < 0) { + log_warning_errno(fd_d, "Unable to open tty%i, fonts will not be copied: %m", i); continue; + } - xsprintf(vcname, "/dev/tty%i", i); - vcfd = open_terminal(vcname, O_RDWR|O_CLOEXEC); - if (vcfd < 0) + if (!is_settable(fd_d)) continue; - /* copy font from active VT, where the font was uploaded to */ - cfo.op = KD_FONT_OP_COPY; - cfo.height = vcs.v_active-1; /* tty1 == index 0 */ - (void) ioctl(vcfd, KDFONTOP, &cfo); + toggle_utf8(ttyname, fd_d, utf8); - /* copy map of 8bit chars */ - if (ioctl(fd, GIO_SCRNMAP, map8) >= 0) - (void) ioctl(vcfd, PIO_SCRNMAP, map8); + if (cfo.op != KD_FONT_OP_SET) + continue; - /* copy map of 8bit chars -> 16bit Unicode values */ - if (ioctl(fd, GIO_UNISCRNMAP, map16) >= 0) - (void) ioctl(vcfd, PIO_UNISCRNMAP, map16); + r = ioctl(fd_d, KDFONTOP, &cfo); + if (r < 0) { + log_warning_errno(errno, "KD_FONT_OP_SET failed, fonts will not be copied to tty%i: %m", i); + continue; + } /* copy unicode translation table */ /* unimapd is a ushort count and a pointer to an array of struct unipair { ushort, ushort } */ - unimapd.entries = unipairs; - unimapd.entry_ct = USHRT_MAX; - if (ioctl(fd, GIO_UNIMAP, &unimapd) >= 0) { - struct unimapinit adv = { 0, 0, 0 }; + r = ioctl(fd_d, PIO_UNIMAPCLR, &adv); + if (r < 0) { + log_warning_errno(errno, "PIO_UNIMAPCLR failed, unimaps might be incorrect for tty%i: %m", i); + continue; + } - (void) ioctl(vcfd, PIO_UNIMAPCLR, &adv); - (void) ioctl(vcfd, PIO_UNIMAP, &unimapd); + r = ioctl(fd_d, PIO_UNIMAP, &unimapd); + if (r < 0) { + log_warning_errno(errno, "PIO_UNIMAP failed, unimaps might be incorrect for tty%i: %m", i); + continue; } + + log_debug("Font and unimap successfully copied to %s", ttyname); } } @@ -290,6 +355,16 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } + if (!is_allocated_byfd(fd)) { + log_error("Virtual console %s is not allocated.", vc); + return EXIT_FAILURE; + } + + if (!is_settable(fd)) { + log_error("Virtual console %s is not in K_XLATE or K_UNICODE.", vc); + return EXIT_FAILURE; + } + utf8 = is_locale_utf8(); r = parse_env_file("/etc/vconsole.conf", NEWLINE, @@ -307,8 +382,12 @@ int main(int argc, char **argv) { if (detect_container() <= 0) { r = parse_env_file("/proc/cmdline", WHITESPACE, "vconsole.keymap", &vc_keymap, - "vconsole.keymap.toggle", &vc_keymap_toggle, + "vconsole.keymap_toggle", &vc_keymap_toggle, "vconsole.font", &vc_font, + "vconsole.font_map", &vc_font_map, + "vconsole.font_unimap", &vc_font_unimap, + /* compatibility with obsolete multiple-dot scheme */ + "vconsole.keymap.toggle", &vc_keymap_toggle, "vconsole.font.map", &vc_font_map, "vconsole.font.unimap", &vc_font_unimap, NULL); @@ -317,17 +396,17 @@ int main(int argc, char **argv) { log_warning_errno(r, "Failed to read /proc/cmdline: %m"); } - if (utf8) - (void) enable_utf8(fd); - else - (void) disable_utf8(fd); + toggle_utf8_sysfs(utf8); + toggle_utf8(vc, fd, utf8); + font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) == 0; + keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) == 0; - font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) > 0; - keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) > 0; - - /* Only copy the font when we executed setfont successfully */ - if (font_copy && font_ok) - (void) font_copy_to_all_vcs(fd); + if (font_copy) { + if (font_ok) + setup_remaining_vcs(fd, utf8); + else + log_warning("Setting source virtual console failed, ignoring remaining ones"); + } return font_ok && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/grp-initprogs/systemd-vconsole-setup/vconsole.conf.xml b/src/grp-initprogs/systemd-vconsole-setup/vconsole.conf.xml index 27196d44e9..fa30ca6569 100644 --- a/src/grp-initprogs/systemd-vconsole-setup/vconsole.conf.xml +++ b/src/grp-initprogs/systemd-vconsole-setup/vconsole.conf.xml @@ -55,8 +55,9 @@ <para>The <filename>/etc/vconsole.conf</filename> file configures the virtual console, i.e. keyboard mapping and console font. It is - applied at boot by - <citerefentry><refentrytitle>systemd-vconsole-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para> + applied at boot by udev using <filename>90-vconsole.rules</filename> file. + You can safely mask this file if you want to avoid this kind of initialization. + </para> <para>The basic file format of the <filename>vconsole.conf</filename> is a newline-separated list of @@ -68,10 +69,10 @@ <para>Note that the kernel command line options <varname>vconsole.keymap=</varname>, - <varname>vconsole.keymap.toggle=</varname>, + <varname>vconsole.keymap_toggle=</varname>, <varname>vconsole.font=</varname>, - <varname>vconsole.font.map=</varname>, - <varname>vconsole.font.unimap=</varname> may be used + <varname>vconsole.font_map=</varname>, + <varname>vconsole.font_unimap=</varname> may be used to override the console settings at boot.</para> <para>Depending on the operating system other configuration files @@ -90,12 +91,10 @@ <term><varname>KEYMAP=</varname></term> <term><varname>KEYMAP_TOGGLE=</varname></term> - <listitem><para>Configures the key mapping table for the - keyboard. <varname>KEYMAP=</varname> defaults to - <literal>us</literal> if not set. The - <varname>KEYMAP_TOGGLE=</varname> can be used to configure a - second toggle keymap and is by default - unset.</para></listitem> + <listitem><para>Configures the key mapping table for the keyboard. + <varname>KEYMAP=</varname> defaults to <literal>us</literal> if not set. The + <varname>KEYMAP_TOGGLE=</varname> can be used to configure a second toggle keymap and is by + default unset.</para></listitem> </varlistentry> <varlistentry> @@ -111,6 +110,32 @@ </refsect1> <refsect1> + <title>Kernel Command Line</title> + + <para>A few configuration parameters from <filename>vconsole.conf</filename> may be overridden + on the kernel command line:</para> + + <variablelist class='kernel-commandline-options'> + <varlistentry> + <term><varname>vconsole.keymap=</varname></term> + <term><varname>vconsole.keymap_toggle=</varname></term> + + <listitem><para>Overrides <varname>KEYMAP=</varname> and <varname>KEYMAP_TOGGLE=</varname>. + </para></listitem> + </varlistentry> + <varlistentry> + + <term><varname>vconsole.font=</varname></term> + <term><varname>vconsole.font_map=</varname></term> + <term><varname>vconsole.font_unimap=</varname></term> + + <listitem><para>Overrides <varname>FONT=</varname>, <varname>FONT_MAP=</varname>, and + <varname>FONT_UNIMAP=</varname>.</para></listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> <title>Example</title> <example> |