From 1fd04a72d752328773c818df0f2a71bb8d079bed Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 29 Nov 2016 22:26:10 -0500 Subject: ./tools/notsd-move --- .../systemd-vconsole-setup/.gitignore | 1 + .../systemd-vconsole-setup/90-vconsole.rules.in | 10 + src/grp-initprogs/systemd-vconsole-setup/Makefile | 50 ++++ .../systemd-vconsole-setup.service.in | 19 ++ .../systemd-vconsole-setup.service.xml | 114 +++++++ .../systemd-vconsole-setup/vconsole-setup.c | 333 +++++++++++++++++++++ .../systemd-vconsole-setup/vconsole.conf.xml | 139 +++++++++ 7 files changed, 666 insertions(+) create mode 100644 src/grp-initprogs/systemd-vconsole-setup/.gitignore create mode 100644 src/grp-initprogs/systemd-vconsole-setup/90-vconsole.rules.in create mode 100644 src/grp-initprogs/systemd-vconsole-setup/Makefile create mode 100644 src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.in create mode 100644 src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.xml create mode 100644 src/grp-initprogs/systemd-vconsole-setup/vconsole-setup.c create mode 100644 src/grp-initprogs/systemd-vconsole-setup/vconsole.conf.xml (limited to 'src/grp-initprogs/systemd-vconsole-setup') diff --git a/src/grp-initprogs/systemd-vconsole-setup/.gitignore b/src/grp-initprogs/systemd-vconsole-setup/.gitignore new file mode 100644 index 0000000000..82741b2fb3 --- /dev/null +++ b/src/grp-initprogs/systemd-vconsole-setup/.gitignore @@ -0,0 +1 @@ +/90-vconsole.rules diff --git a/src/grp-initprogs/systemd-vconsole-setup/90-vconsole.rules.in b/src/grp-initprogs/systemd-vconsole-setup/90-vconsole.rules.in new file mode 100644 index 0000000000..35b9ad5151 --- /dev/null +++ b/src/grp-initprogs/systemd-vconsole-setup/90-vconsole.rules.in @@ -0,0 +1,10 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# Each vtcon keeps its own state of fonts. +# +ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", RUN+="@rootlibexecdir@/systemd-vconsole-setup" diff --git a/src/grp-initprogs/systemd-vconsole-setup/Makefile b/src/grp-initprogs/systemd-vconsole-setup/Makefile new file mode 100644 index 0000000000..5a93ae780b --- /dev/null +++ b/src/grp-initprogs/systemd-vconsole-setup/Makefile @@ -0,0 +1,50 @@ +# -*- Mode: makefile; indent-tabs-mode: t -*- +# +# This file is part of systemd. +# +# Copyright 2010-2012 Lennart Poettering +# Copyright 2010-2012 Kay Sievers +# Copyright 2013 Zbigniew JÄ™drzejewski-Szmek +# Copyright 2013 David Strauss +# Copyright 2016 Luke Shumaker +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . +include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk +include $(topsrcdir)/build-aux/Makefile.head.mk + +ifneq ($(ENABLE_VCONSOLE),) +systemd_vconsole_setup_SOURCES = \ + src/vconsole/vconsole-setup.c + +systemd_vconsole_setup_LDADD = \ + libsystemd-shared.la + +rootlibexec_PROGRAMS += \ + systemd-vconsole-setup + +nodist_udevrules_DATA += \ + src/vconsole/90-vconsole.rules + +nodist_systemunit_DATA += \ + units/systemd-vconsole-setup.service + +SYSINIT_TARGET_WANTS += \ + systemd-vconsole-setup.service +endif # ENABLE_VCONSOLE + +EXTRA_DIST += \ + src/vconsole/90-vconsole.rules.in \ + units/systemd-vconsole-setup.service.in + +include $(topsrcdir)/build-aux/Makefile.tail.mk 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 new file mode 100644 index 0000000000..6160361871 --- /dev/null +++ b/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.in @@ -0,0 +1,19 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +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 new file mode 100644 index 0000000000..ff079761c1 --- /dev/null +++ b/src/grp-initprogs/systemd-vconsole-setup/systemd-vconsole-setup.service.xml @@ -0,0 +1,114 @@ + + + + + + + + systemd-vconsole-setup.service + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + systemd-vconsole-setup.service + 8 + + + + systemd-vconsole-setup.service + systemd-vconsole-setup + Configure the virtual console at boot + + + + systemd-vconsole-setup.service + /usr/lib/systemd/systemd-vconsole-setup + + + + Description + + systemd-vconsole-setup.service is an + early boot service that configures the virtual console font and + console keymap. Internally it calls + loadkeys1 + and + setfont8. + + See + vconsole.conf5 + for information about the configuration files understood by this + service. + + + + + + Kernel Command Line + + A few configuration parameters from + vconsole.conf may be overridden on the kernel + command line: + + + + vconsole.keymap= + vconsole.keymap.toggle= + + Overrides the key mapping table for the + keyboard and the second toggle keymap. + + + + vconsole.font= + vconsole.font.map= + vconsole.font.unimap= + + Configures the console font, the console map, + and the unicode font map. + + + + See + vconsole.conf5 + for information about these settings. + + + + See Also + + systemd1, + vconsole.conf5, + loadkeys1, + setfont8, + systemd-localed.service8 + + + + diff --git a/src/grp-initprogs/systemd-vconsole-setup/vconsole-setup.c b/src/grp-initprogs/systemd-vconsole-setup/vconsole-setup.c new file mode 100644 index 0000000000..7edab74051 --- /dev/null +++ b/src/grp-initprogs/systemd-vconsole-setup/vconsole-setup.c @@ -0,0 +1,333 @@ +/*** + This file is part of systemd. + + Copyright 2010 Kay Sievers + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "systemd-basic/alloc-util.h" +#include "systemd-basic/fd-util.h" +#include "systemd-basic/fileio.h" +#include "systemd-basic/io-util.h" +#include "systemd-basic/locale-util.h" +#include "systemd-basic/log.h" +#include "systemd-basic/process-util.h" +#include "systemd-basic/signal-util.h" +#include "systemd-basic/stdio-util.h" +#include "systemd-basic/string-util.h" +#include "systemd-basic/terminal-util.h" +#include "systemd-basic/util.h" +#include "systemd-basic/virt.h" + +static bool is_vconsole(int fd) { + unsigned char data[1]; + + data[0] = TIOCL_GETFGCONSOLE; + return ioctl(fd, TIOCLINUX, data) >= 0; +} + +static int disable_utf8(int fd) { + int r = 0, k; + + if (ioctl(fd, KDSKBMODE, K_XLATE) < 0) + r = -errno; + + k = loop_write(fd, "\033%@", 3, false); + if (k < 0) + r = k; + + k = write_string_file("/sys/module/vt/parameters/default_utf8", "0", 0); + if (k < 0) + r = k; + + if (r < 0) + log_warning_errno(r, "Failed to disable UTF-8: %m"); + + return r; +} + +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; + } + + k = loop_write(fd, "\033%G", 3, false); + if (k < 0) + r = k; + + k = write_string_file("/sys/module/vt/parameters/default_utf8", "1", 0); + if (k < 0) + r = k; + + if (r < 0) + log_warning_errno(r, "Failed to enable UTF-8: %m"); + + return r; +} + +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; + pid_t pid; + + /* An empty map means kernel map */ + if (isempty(map)) + return 1; + + args[i++] = KBD_LOADKEYS; + args[i++] = "-q"; + args[i++] = "-C"; + args[i++] = vc; + if (utf8) + args[i++] = "-u"; + args[i++] = map; + if (map_toggle) + args[i++] = map_toggle; + args[i++] = NULL; + + pid = fork(); + if (pid < 0) + return log_error_errno(errno, "Failed to fork: %m"); + else if (pid == 0) { + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + + execv(args[0], (char **) args); + _exit(EXIT_FAILURE); + } + + r = wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true); + if (r < 0) + return r; + + return r == 0; +} + +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; + pid_t pid; + + /* An empty font means kernel font */ + if (isempty(font)) + return 1; + + args[i++] = KBD_SETFONT; + args[i++] = "-C"; + args[i++] = vc; + args[i++] = font; + if (map) { + args[i++] = "-m"; + args[i++] = map; + } + if (unimap) { + args[i++] = "-u"; + args[i++] = unimap; + } + args[i++] = NULL; + + pid = fork(); + if (pid < 0) + return log_error_errno(errno, "Failed to fork: %m"); + else if (pid == 0) { + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + + execv(args[0], (char **) args); + _exit(EXIT_FAILURE); + } + + r = wait_for_terminate_and_warn(KBD_SETFONT, pid, true); + if (r < 0) + return r; + + return r == 0; +} + +/* + * A newly allocated VT uses the font from the active VT. Here + * 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. + */ +static void font_copy_to_all_vcs(int fd) { + struct vt_stat vcs = {}; + unsigned char map8[E_TABSZ]; + unsigned short map16[E_TABSZ]; + struct unimapdesc unimapd; + _cleanup_free_ struct unipair* unipairs = NULL; + int i, r; + + unipairs = new(struct unipair, USHRT_MAX); + if (!unipairs) { + log_oom(); + return; + } + + /* 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"); + 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 = {}; + + if (i == vcs.v_active) + continue; + + /* skip non-allocated ttys */ + xsprintf(vcname, "/dev/vcs%i", i); + if (access(vcname, F_OK) < 0) + continue; + + xsprintf(vcname, "/dev/tty%i", i); + vcfd = open_terminal(vcname, O_RDWR|O_CLOEXEC); + if (vcfd < 0) + 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); + + /* copy map of 8bit chars */ + if (ioctl(fd, GIO_SCRNMAP, map8) >= 0) + (void) ioctl(vcfd, PIO_SCRNMAP, map8); + + /* copy map of 8bit chars -> 16bit Unicode values */ + if (ioctl(fd, GIO_UNISCRNMAP, map16) >= 0) + (void) ioctl(vcfd, PIO_UNISCRNMAP, map16); + + /* 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 }; + + (void) ioctl(vcfd, PIO_UNIMAPCLR, &adv); + (void) ioctl(vcfd, PIO_UNIMAP, &unimapd); + } + } +} + +int main(int argc, char **argv) { + const char *vc; + _cleanup_free_ char + *vc_keymap = NULL, *vc_keymap_toggle = NULL, + *vc_font = NULL, *vc_font_map = NULL, *vc_font_unimap = NULL; + _cleanup_close_ int fd = -1; + bool utf8, font_copy = false, font_ok, keyboard_ok; + int r = EXIT_FAILURE; + + log_set_target(LOG_TARGET_AUTO); + log_parse_environment(); + log_open(); + + umask(0022); + + if (argv[1]) + vc = argv[1]; + else { + vc = "/dev/tty0"; + font_copy = true; + } + + fd = open_terminal(vc, O_RDWR|O_CLOEXEC); + if (fd < 0) { + log_error_errno(fd, "Failed to open %s: %m", vc); + return EXIT_FAILURE; + } + + if (!is_vconsole(fd)) { + log_error("Device %s is not a virtual console.", vc); + return EXIT_FAILURE; + } + + utf8 = is_locale_utf8(); + + r = parse_env_file("/etc/vconsole.conf", NEWLINE, + "KEYMAP", &vc_keymap, + "KEYMAP_TOGGLE", &vc_keymap_toggle, + "FONT", &vc_font, + "FONT_MAP", &vc_font_map, + "FONT_UNIMAP", &vc_font_unimap, + NULL); + + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read /etc/vconsole.conf: %m"); + + /* Let the kernel command line override /etc/vconsole.conf */ + if (detect_container() <= 0) { + r = parse_env_file("/proc/cmdline", WHITESPACE, + "vconsole.keymap", &vc_keymap, + "vconsole.keymap.toggle", &vc_keymap_toggle, + "vconsole.font", &vc_font, + "vconsole.font.map", &vc_font_map, + "vconsole.font.unimap", &vc_font_unimap, + NULL); + + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read /proc/cmdline: %m"); + } + + if (utf8) + (void) enable_utf8(fd); + else + (void) disable_utf8(fd); + + 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); + + 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 new file mode 100644 index 0000000000..27196d44e9 --- /dev/null +++ b/src/grp-initprogs/systemd-vconsole-setup/vconsole.conf.xml @@ -0,0 +1,139 @@ + + + + + + + + vconsole.conf + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + vconsole.conf + 5 + + + + vconsole.conf + Configuration file for the virtual console + + + + /etc/vconsole.conf + + + + Description + + The /etc/vconsole.conf file configures + the virtual console, i.e. keyboard mapping and console font. It is + applied at boot by + systemd-vconsole-setup.service8. + + The basic file format of the + vconsole.conf is a newline-separated list of + environment-like shell-compatible variable assignments. It is + possible to source the configuration from shell scripts, however, + beyond mere variable assignments no shell features are supported, + allowing applications to read the file without implementing a + shell compatible execution engine. + + Note that the kernel command line options + vconsole.keymap=, + vconsole.keymap.toggle=, + vconsole.font=, + vconsole.font.map=, + vconsole.font.unimap= may be used + to override the console settings at boot. + + Depending on the operating system other configuration files + might be checked for configuration of the virtual console as well, + however only as fallback. + + + + Options + + The following options are understood: + + + + + KEYMAP= + KEYMAP_TOGGLE= + + Configures the key mapping table for the + keyboard. KEYMAP= defaults to + us if not set. The + KEYMAP_TOGGLE= can be used to configure a + second toggle keymap and is by default + unset. + + + + FONT= + FONT_MAP= + FONT_UNIMAP= + + Configures the console font, the console map + and the unicode font map. + + + + + + + Example + + + German keyboard and console + + /etc/vconsole.conf: + + KEYMAP=de-latin1 +FONT=eurlatgr + + + + + + See Also + + systemd1, + systemd-vconsole-setup.service8, + loadkeys1, + setfont8, + locale.conf5, + systemd-localed.service8 + + + + -- cgit v1.2.3-54-g00ecf