1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Kay Sievers
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
34 #include <sys/ioctl.h>
36 #include <linux/tiocl.h>
43 static bool is_console(int fd) {
44 unsigned char data[1];
46 data[0] = TIOCL_GETFGCONSOLE;
47 return ioctl(fd, TIOCLINUX, data) >= 0;
50 static bool is_locale_utf8(void) {
53 if (!setlocale(LC_ALL, ""))
56 set = nl_langinfo(CODESET);
60 return streq(set, "UTF-8");
63 static int disable_utf8(int fd) {
66 if (ioctl(fd, KDSKBMODE, K_XLATE) < 0)
69 if (loop_write(fd, "\033%@", 3, false) < 0)
72 if ((k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "0")) < 0)
76 log_warning("Failed to disable UTF-8: %s", strerror(errno));
81 static int load_keymap(const char *vc, const char *map, bool utf8, pid_t *_pid) {
86 args[i++] = "/bin/loadkeys";
95 if ((pid = fork()) < 0) {
96 log_error("Failed to fork: %m");
98 } else if (pid == 0) {
99 execv(args[0], (char **) args);
107 static int load_font(const char *vc, const char *font, const char *map, const char *unimap, pid_t *_pid) {
112 args[i++] = "/bin/setfont";
126 if ((pid = fork()) < 0) {
127 log_error("Failed to fork: %m");
129 } else if (pid == 0) {
130 execv(args[0], (char **) args);
138 int main(int argc, char **argv) {
140 char *vc_keymap = NULL;
141 char *vc_font = NULL;
142 char *vc_font_map = NULL;
143 char *vc_font_unimap = NULL;
146 int r = EXIT_FAILURE;
147 pid_t font_pid = 0, keymap_pid = 0;
149 log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
150 log_parse_environment();
158 if ((fd = open(vc, O_RDWR|O_CLOEXEC)) < 0) {
159 log_error("Failed to open %s: %m", vc);
163 if (!is_console(fd)) {
164 log_error("Device %s is not a virtual console.", vc);
168 if (!(utf8 = is_locale_utf8()))
172 if ((r = parse_env_file("/etc/sysconfig/i18n", NEWLINE,
177 log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r));
180 if ((r = parse_env_file("/etc/sysconfig/keyboard", NEWLINE,
181 "KEYTABLE", &vc_keymap,
185 log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r));
189 /* Override distribution-specific options with the
190 * distribution-independent configuration */
191 if ((r = parse_env_file("/etc/vconsole", NEWLINE,
192 "VCONSOLE_KEYMAP", &vc_keymap,
193 "VCONSOLE_FONT", &vc_font,
194 "VCONSOLE_FONT_MAP", &vc_font_map,
195 "VCONSOLE_FONT_UNIMAP", &vc_font_unimap,
199 log_warning("Failed to read /etc/vconsole: %s", strerror(-r));
202 if ((r = parse_env_file("/proc/cmdline", WHITESPACE,
205 "KEYTABLE", &vc_keymap,
207 "vconsole.keymap", &vc_keymap,
208 "vconsole.font", &vc_font,
209 "vconsole.font.map", &vc_font_map,
210 "vconsole.font.unimap", &vc_font_unimap,
214 log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
218 vc_keymap = strdup("us");
220 vc_font = strdup("latarcyrheb-sun16");
222 if (!vc_keymap || !vc_font) {
223 log_error("Failed to allocate strings.");
227 if (load_keymap(vc, vc_keymap, utf8, &keymap_pid) >= 0 &&
228 load_font(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid) >= 0)
233 wait_for_terminate_and_warn("/bin/loadkeys", keymap_pid);
236 wait_for_terminate_and_warn("/bin/setfont", font_pid);
241 free(vc_font_unimap);
244 close_nointr_nofail(fd);