]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/vconsole/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 Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include <sys/ioctl.h>
34 #include <linux/tiocl.h>
42 static bool is_vconsole(int fd
) {
43 unsigned char data
[1];
45 data
[0] = TIOCL_GETFGCONSOLE
;
46 return ioctl(fd
, TIOCLINUX
, data
) >= 0;
49 static int disable_utf8(int fd
) {
52 if (ioctl(fd
, KDSKBMODE
, K_XLATE
) < 0)
55 if (loop_write(fd
, "\033%@", 3, false) < 0)
58 k
= write_one_line_file("/sys/module/vt/parameters/default_utf8", "0");
63 log_warning("Failed to disable UTF-8: %s", strerror(-r
));
68 static int enable_utf8(int fd
) {
71 if (ioctl(fd
, KDSKBMODE
, K_UNICODE
) < 0)
74 if (loop_write(fd
, "\033%G", 3, false) < 0)
77 k
= write_one_line_file("/sys/module/vt/parameters/default_utf8", "1");
82 log_warning("Failed to enable UTF-8: %s", strerror(-r
));
87 static int load_keymap(const char *vc
, const char *map
, const char *map_toggle
, bool utf8
, pid_t
*_pid
) {
93 /* An empty map means kernel map */
98 args
[i
++] = KBD_LOADKEYS
;
106 args
[i
++] = map_toggle
;
111 log_error("Failed to fork: %m");
113 } else if (pid
== 0) {
114 execv(args
[0], (char **) args
);
122 static int load_font(const char *vc
, const char *font
, const char *map
, const char *unimap
, pid_t
*_pid
) {
128 /* An empty font means kernel font */
133 args
[i
++] = KBD_SETFONT
;
149 log_error("Failed to fork: %m");
151 } else if (pid
== 0) {
152 execv(args
[0], (char **) args
);
160 int main(int argc
, char **argv
) {
162 char *vc_keymap
= NULL
;
163 char *vc_keymap_toggle
= NULL
;
164 char *vc_font
= NULL
;
165 char *vc_font_map
= NULL
;
166 char *vc_font_unimap
= NULL
;
168 char *vc_unicode
= NULL
;
170 #if defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
171 char *vc_keytable
= NULL
;
175 int r
= EXIT_FAILURE
;
176 pid_t font_pid
= 0, keymap_pid
= 0;
178 log_set_target(LOG_TARGET_AUTO
);
179 log_parse_environment();
189 fd
= open_terminal(vc
, O_RDWR
|O_CLOEXEC
);
191 log_error("Failed to open %s: %m", vc
);
195 if (!is_vconsole(fd
)) {
196 log_error("Device %s is not a virtual console.", vc
);
200 utf8
= is_locale_utf8();
204 if (detect_container(NULL
) <= 0) {
205 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
206 "vconsole.keymap", &vc_keymap
,
207 "vconsole.keymap.toggle", &vc_keymap_toggle
,
208 "vconsole.font", &vc_font
,
209 "vconsole.font.map", &vc_font_map
,
210 "vconsole.font.unimap", &vc_font_unimap
,
213 if (r
< 0 && r
!= -ENOENT
)
214 log_warning("Failed to read /proc/cmdline: %s", strerror(-r
));
217 /* Hmm, nothing set on the kernel cmd line? Then let's
218 * try /etc/vconsole.conf */
220 r
= parse_env_file("/etc/vconsole.conf", NEWLINE
,
221 "KEYMAP", &vc_keymap
,
222 "KEYMAP_TOGGLE", &vc_keymap_toggle
,
224 "FONT_MAP", &vc_font_map
,
225 "FONT_UNIMAP", &vc_font_unimap
,
228 if (r
< 0 && r
!= -ENOENT
)
229 log_warning("Failed to read /etc/vconsole.conf: %s", strerror(-r
));
233 #if defined(TARGET_SUSE)
234 r
= parse_env_file("/etc/sysconfig/keyboard", NEWLINE
,
235 "KEYTABLE", &vc_keymap
,
237 if (r
< 0 && r
!= -ENOENT
)
238 log_warning("Failed to read /etc/sysconfig/keyboard: %s", strerror(-r
));
240 r
= parse_env_file("/etc/sysconfig/console", NEWLINE
,
241 "CONSOLE_FONT", &vc_font
,
242 "CONSOLE_SCREENMAP", &vc_font_map
,
243 "CONSOLE_UNICODEMAP", &vc_font_unimap
,
245 if (r
< 0 && r
!= -ENOENT
)
246 log_warning("Failed to read /etc/sysconfig/console: %s", strerror(-r
));
248 #elif defined(TARGET_ARCH)
249 r
= parse_env_file("/etc/rc.conf", NEWLINE
,
250 "KEYMAP", &vc_keymap
,
251 "CONSOLEFONT", &vc_font
,
252 "CONSOLEMAP", &vc_font_map
,
254 if (r
< 0 && r
!= -ENOENT
)
255 log_warning("Failed to read /etc/rc.conf: %s", strerror(-r
));
257 #elif defined(TARGET_ALTLINUX)
258 r
= parse_env_file("/etc/sysconfig/keyboard", NEWLINE
,
259 "KEYTABLE", &vc_keymap
,
261 if (r
< 0 && r
!= -ENOENT
)
262 log_warning("Failed to read /etc/sysconfig/keyboard: %s", strerror(-r
));
264 r
= parse_env_file("/etc/sysconfig/consolefont", NEWLINE
,
267 if (r
< 0 && r
!= -ENOENT
)
268 log_warning("Failed to read /etc/sysconfig/consolefont: %s", strerror(-r
));
270 #elif defined(TARGET_GENTOO)
271 r
= parse_env_file("/etc/rc.conf", NEWLINE
,
272 "unicode", &vc_unicode
,
274 if (r
< 0 && r
!= -ENOENT
)
275 log_warning("Failed to read /etc/rc.conf: %s", strerror(-r
));
280 rc_unicode
= parse_boolean(vc_unicode
);
282 log_warning("Unknown value for /etc/rc.conf unicode=%s", vc_unicode
);
284 if (rc_unicode
&& !utf8
)
285 log_warning("/etc/rc.conf wants unicode, but current locale is not UTF-8 capable!");
286 else if (!rc_unicode
&& utf8
) {
287 log_debug("/etc/rc.conf does not want unicode, leave it on in kernel but does not apply to vconsole.");
293 /* /etc/conf.d/consolefont comments and gentoo
294 * documentation mention uppercase, but the actual
295 * contents are lowercase. the existing
296 * /etc/init.d/consolefont tries both
298 r
= parse_env_file("/etc/conf.d/consolefont", NEWLINE
,
299 "CONSOLEFONT", &vc_font
,
300 "consolefont", &vc_font
,
301 "consoletranslation", &vc_font_map
,
302 "CONSOLETRANSLATION", &vc_font_map
,
303 "unicodemap", &vc_font_unimap
,
304 "UNICODEMAP", &vc_font_unimap
,
306 if (r
< 0 && r
!= -ENOENT
)
307 log_warning("Failed to read /etc/conf.d/consolefont: %s", strerror(-r
));
309 r
= parse_env_file("/etc/conf.d/keymaps", NEWLINE
,
310 "keymap", &vc_keymap
,
311 "KEYMAP", &vc_keymap
,
313 if (r
< 0 && r
!= -ENOENT
)
314 log_warning("Failed to read /etc/conf.d/keymaps: %s", strerror(-r
));
316 #elif defined(TARGET_MANDRIVA) || defined (TARGET_MAGEIA)
318 r
= parse_env_file("/etc/sysconfig/i18n", NEWLINE
,
320 "SYSFONTACM", &vc_font_map
,
321 "UNIMAP", &vc_font_unimap
,
323 if (r
< 0 && r
!= -ENOENT
)
324 log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r
));
326 r
= parse_env_file("/etc/sysconfig/keyboard", NEWLINE
,
327 "KEYTABLE", &vc_keytable
,
328 "KEYMAP", &vc_keymap
,
329 "UNIKEYTABLE", &vc_keymap
,
330 "GRP_TOGGLE", &vc_keymap_toggle
,
332 if (r
< 0 && r
!= -ENOENT
)
333 log_warning("Failed to read /etc/sysconfig/keyboard: %s", strerror(-r
));
338 if (endswith(vc_keytable
, ".uni") || strstr(vc_keytable
, ".uni."))
339 vc_keymap
= strdup(vc_keytable
);
342 s
= strstr(vc_keytable
, ".map");
344 vc_keytable
[s
-vc_keytable
+1] = '\0';
345 vc_keymap
= strappend(vc_keytable
, ".uni");
348 vc_keymap
= strdup(vc_keytable
);
358 if (access("/etc/sysconfig/console/default.kmap", F_OK
) >= 0) {
361 t
= strdup("/etc/sysconfig/console/default.kmap");
381 if (load_keymap(vc
, vc_keymap
, vc_keymap_toggle
, utf8
, &keymap_pid
) >= 0 &&
382 load_font(vc
, vc_font
, vc_font_map
, vc_font_unimap
, &font_pid
) >= 0)
387 wait_for_terminate_and_warn(KBD_LOADKEYS
, keymap_pid
);
390 wait_for_terminate_and_warn(KBD_SETFONT
, font_pid
);
395 free(vc_font_unimap
);
398 close_nointr_nofail(fd
);