]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/vconsole-setup.c
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_vconsole(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
, const char *map_toggle
, bool utf8
, pid_t
*_pid
) {
87 /* An empty map means kernel map */
92 args
[i
++] = KBD_LOADKEYS
;
100 args
[i
++] = map_toggle
;
103 if ((pid
= fork()) < 0) {
104 log_error("Failed to fork: %m");
106 } else if (pid
== 0) {
107 execv(args
[0], (char **) args
);
115 static int load_font(const char *vc
, const char *font
, const char *map
, const char *unimap
, pid_t
*_pid
) {
121 /* An empty font means kernel font */
126 args
[i
++] = KBD_SETFONT
;
140 if ((pid
= fork()) < 0) {
141 log_error("Failed to fork: %m");
143 } else if (pid
== 0) {
144 execv(args
[0], (char **) args
);
152 int main(int argc
, char **argv
) {
154 char *vc_keymap
= NULL
;
155 char *vc_keymap_toggle
= NULL
;
156 char *vc_font
= NULL
;
157 char *vc_font_map
= NULL
;
158 char *vc_font_unimap
= NULL
;
160 char *vc_unicode
= NULL
;
162 #ifdef TARGET_MANDRIVA
163 char *vc_keytable
= NULL
;
167 int r
= EXIT_FAILURE
;
168 pid_t font_pid
= 0, keymap_pid
= 0;
170 log_set_target(LOG_TARGET_AUTO
);
171 log_parse_environment();
179 if ((fd
= open(vc
, O_RDWR
|O_CLOEXEC
)) < 0) {
180 log_error("Failed to open %s: %m", vc
);
184 if (!is_vconsole(fd
)) {
185 log_error("Device %s is not a virtual console.", vc
);
189 utf8
= is_locale_utf8();
191 vc_keymap
= strdup("us");
192 vc_font
= strdup(DEFAULT_FONT
);
194 if (!vc_keymap
|| !vc_font
) {
195 log_error("Failed to allocate strings.");
201 if (detect_container(NULL
) <= 0)
202 if ((r
= parse_env_file("/proc/cmdline", WHITESPACE
,
203 #if defined(TARGET_FEDORA) || defined(TARGET_MEEGO)
205 "KEYTABLE", &vc_keymap
,
207 "vconsole.keymap", &vc_keymap
,
208 "vconsole.keymap.toggle", &vc_keymap_toggle
,
209 "vconsole.font", &vc_font
,
210 "vconsole.font.map", &vc_font_map
,
211 "vconsole.font.unimap", &vc_font_unimap
,
215 log_warning("Failed to read /proc/cmdline: %s", strerror(-r
));
218 /* Hmm, nothing set on the kernel cmd line? Then let's
219 * try /etc/vconsole.conf */
221 (r
= parse_env_file("/etc/vconsole.conf", NEWLINE
,
222 "KEYMAP", &vc_keymap
,
223 "KEYMAP_TOGGLE", &vc_keymap_toggle
,
225 "FONT_MAP", &vc_font_map
,
226 "FONT_UNIMAP", &vc_font_unimap
,
230 log_warning("Failed to read /etc/vconsole.conf: %s", strerror(-r
));
234 #if defined(TARGET_FEDORA) || defined(TARGET_MEEGO)
235 if ((r
= parse_env_file("/etc/sysconfig/i18n", NEWLINE
,
237 "SYSFONTACM", &vc_font_map
,
238 "UNIMAP", &vc_font_unimap
,
242 log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r
));
245 if ((r
= parse_env_file("/etc/sysconfig/keyboard", NEWLINE
,
246 "KEYTABLE", &vc_keymap
,
247 "KEYMAP", &vc_keymap
,
251 log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r
));
254 if (access("/etc/sysconfig/console/default.kmap", F_OK
) >= 0) {
257 if (!(t
= strdup("/etc/sysconfig/console/default.kmap"))) {
258 log_error("Out of memory.");
266 #elif defined(TARGET_SUSE)
267 if ((r
= parse_env_file("/etc/sysconfig/keyboard", NEWLINE
,
268 "KEYTABLE", &vc_keymap
,
272 log_warning("Failed to read /etc/sysconfig/keyboard: %s", strerror(-r
));
275 if ((r
= parse_env_file("/etc/sysconfig/console", NEWLINE
,
276 "CONSOLE_FONT", &vc_font
,
277 "CONSOLE_SCREENMAP", &vc_font_map
,
278 "CONSOLE_UNICODEMAP", &vc_font_unimap
,
282 log_warning("Failed to read /etc/sysconfig/console: %s", strerror(-r
));
285 #elif defined(TARGET_ARCH)
286 if ((r
= parse_env_file("/etc/rc.conf", NEWLINE
,
287 "KEYMAP", &vc_keymap
,
288 "CONSOLEFONT", &vc_font
,
289 "CONSOLEMAP", &vc_font_map
,
293 log_warning("Failed to read /etc/rc.conf: %s", strerror(-r
));
296 #elif defined(TARGET_FRUGALWARE)
297 if ((r
= parse_env_file("/etc/sysconfig/keymap", NEWLINE
,
298 "keymap", &vc_keymap
,
301 log_warning("Failed to read /etc/sysconfig/keymap: %s", strerror(-r
));
303 if ((r
= parse_env_file("/etc/sysconfig/font", NEWLINE
,
307 log_warning("Failed to read /etc/sysconfig/font: %s", strerror(-r
));
310 #elif defined(TARGET_ALTLINUX)
311 if ((r
= parse_env_file("/etc/sysconfig/keyboard", NEWLINE
,
312 "KEYTABLE", &vc_keymap
,
316 log_warning("Failed to read /etc/sysconfig/keyboard: %s", strerror(-r
));
319 if ((r
= parse_env_file("/etc/sysconfig/consolefont", NEWLINE
,
324 log_warning("Failed to read /etc/sysconfig/console: %s", strerror(-r
));
327 #elif defined(TARGET_GENTOO)
328 if ((r
= parse_env_file("/etc/rc.conf", NEWLINE
,
329 "unicode", &vc_unicode
,
332 log_warning("Failed to read /etc/rc.conf: %s", strerror(-r
));
338 if ((rc_unicode
= parse_boolean(vc_unicode
)) < 0)
339 log_error("Unknown value for /etc/rc.conf unicode=%s", vc_unicode
);
341 if (rc_unicode
&& !utf8
)
342 log_warning("/etc/rc.conf wants unicode, but current locale is not UTF-8 capable!");
343 else if (!rc_unicode
&& utf8
) {
344 log_debug("/etc/rc.conf does not want unicode, leave it on in kernel but does not apply to vconsole.");
350 /* /etc/conf.d/consolefont comments and gentoo
351 * documentation mention uppercase, but the actual
352 * contents are lowercase. the existing
353 * /etc/init.d/consolefont tries both
355 if ((r
= parse_env_file("/etc/conf.d/consolefont", NEWLINE
,
356 "CONSOLEFONT", &vc_font
,
357 "consolefont", &vc_font
,
358 "consoletranslation", &vc_font_map
,
359 "CONSOLETRANSLATION", &vc_font_map
,
360 "unicodemap", &vc_font_unimap
,
361 "UNICODEMAP", &vc_font_unimap
,
364 log_warning("Failed to read /etc/conf.d/consolefont: %s", strerror(-r
));
367 if ((r
= parse_env_file("/etc/conf.d/keymaps", NEWLINE
,
368 "keymap", &vc_keymap
,
369 "KEYMAP", &vc_keymap
,
372 log_warning("Failed to read /etc/conf.d/keymaps: %s", strerror(-r
));
375 #elif defined(TARGET_MANDRIVA)
377 if ((r
= parse_env_file("/etc/sysconfig/i18n", NEWLINE
,
379 "SYSFONTACM", &vc_font_map
,
380 "UNIMAP", &vc_font_unimap
,
384 log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r
));
387 if ((r
= parse_env_file("/etc/sysconfig/keyboard", NEWLINE
,
388 "KEYTABLE", &vc_keytable
,
389 "KEYMAP", &vc_keymap
,
390 "UNIKEYTABLE", &vc_keymap
,
391 "GRP_TOGGLE", &vc_keymap_toggle
,
395 log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r
));
402 if (endswith(vc_keytable
, ".uni") || strstr(vc_keytable
, ".uni."))
403 vc_keymap
= strdup(vc_keytable
);
406 if ((s
= strstr(vc_keytable
, ".map")))
407 vc_keytable
[s
-vc_keytable
+1] = '\0';
408 vc_keymap
= strappend(vc_keytable
, ".uni");
411 vc_keymap
= strdup(vc_keytable
);
416 log_error("Out of memory.");
421 if (access("/etc/sysconfig/console/default.kmap", F_OK
) >= 0) {
424 if (!(t
= strdup("/etc/sysconfig/console/default.kmap"))) {
425 log_error("Out of memory.");
440 if (load_keymap(vc
, vc_keymap
, vc_keymap_toggle
, utf8
, &keymap_pid
) >= 0 &&
441 load_font(vc
, vc_font
, vc_font_map
, vc_font_unimap
, &font_pid
) >= 0)
446 wait_for_terminate_and_warn(KBD_LOADKEYS
, keymap_pid
);
449 wait_for_terminate_and_warn(KBD_SETFONT
, font_pid
);
454 free(vc_font_unimap
);
457 close_nointr_nofail(fd
);