]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/vconsole/vconsole-setup.c
core: drop support for old per-distro configuration files for console, hostname,...
[thirdparty/systemd.git] / src / vconsole / vconsole-setup.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Kay Sievers
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <fcntl.h>
28 #include <ctype.h>
29 #include <stdbool.h>
30 #include <stdarg.h>
31 #include <limits.h>
32 #include <sys/ioctl.h>
33 #include <sys/wait.h>
34 #include <linux/tiocl.h>
35 #include <linux/kd.h>
36
37 #include "util.h"
38 #include "log.h"
39 #include "macro.h"
40 #include "virt.h"
41
42 static bool is_vconsole(int fd) {
43 unsigned char data[1];
44
45 data[0] = TIOCL_GETFGCONSOLE;
46 return ioctl(fd, TIOCLINUX, data) >= 0;
47 }
48
49 static int disable_utf8(int fd) {
50 int r = 0, k;
51
52 if (ioctl(fd, KDSKBMODE, K_XLATE) < 0)
53 r = -errno;
54
55 if (loop_write(fd, "\033%@", 3, false) < 0)
56 r = -errno;
57
58 k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "0");
59 if (k < 0)
60 r = k;
61
62 if (r < 0)
63 log_warning("Failed to disable UTF-8: %s", strerror(-r));
64
65 return r;
66 }
67
68 static int enable_utf8(int fd) {
69 int r = 0, k;
70
71 if (ioctl(fd, KDSKBMODE, K_UNICODE) < 0)
72 r = -errno;
73
74 if (loop_write(fd, "\033%G", 3, false) < 0)
75 r = -errno;
76
77 k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "1");
78 if (k < 0)
79 r = k;
80
81 if (r < 0)
82 log_warning("Failed to enable UTF-8: %s", strerror(-r));
83
84 return r;
85 }
86
87 static int load_keymap(const char *vc, const char *map, const char *map_toggle, bool utf8, pid_t *_pid) {
88 const char *args[8];
89 int i = 0;
90 pid_t pid;
91
92 if (isempty(map)) {
93 /* An empty map means kernel map */
94 *_pid = 0;
95 return 0;
96 }
97
98 args[i++] = KBD_LOADKEYS;
99 args[i++] = "-q";
100 args[i++] = "-C";
101 args[i++] = vc;
102 if (utf8)
103 args[i++] = "-u";
104 args[i++] = map;
105 if (map_toggle)
106 args[i++] = map_toggle;
107 args[i++] = NULL;
108
109 pid = fork();
110 if (pid < 0) {
111 log_error("Failed to fork: %m");
112 return -errno;
113 } else if (pid == 0) {
114 execv(args[0], (char **) args);
115 _exit(EXIT_FAILURE);
116 }
117
118 *_pid = pid;
119 return 0;
120 }
121
122 static int load_font(const char *vc, const char *font, const char *map, const char *unimap, pid_t *_pid) {
123 const char *args[9];
124 int i = 0;
125 pid_t pid;
126
127 if (isempty(font)) {
128 /* An empty font means kernel font */
129 *_pid = 0;
130 return 0;
131 }
132
133 args[i++] = KBD_SETFONT;
134 args[i++] = "-C";
135 args[i++] = vc;
136 args[i++] = font;
137 if (map) {
138 args[i++] = "-m";
139 args[i++] = map;
140 }
141 if (unimap) {
142 args[i++] = "-u";
143 args[i++] = unimap;
144 }
145 args[i++] = NULL;
146
147 pid = fork();
148 if (pid < 0) {
149 log_error("Failed to fork: %m");
150 return -errno;
151 } else if (pid == 0) {
152 execv(args[0], (char **) args);
153 _exit(EXIT_FAILURE);
154 }
155
156 *_pid = pid;
157 return 0;
158 }
159
160 int main(int argc, char **argv) {
161 const char *vc;
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;
167 int fd = -1;
168 bool utf8;
169 int r = EXIT_FAILURE;
170 pid_t font_pid = 0, keymap_pid = 0;
171
172 log_set_target(LOG_TARGET_AUTO);
173 log_parse_environment();
174 log_open();
175
176 umask(0022);
177
178 if (argv[1])
179 vc = argv[1];
180 else
181 vc = "/dev/tty0";
182
183 fd = open_terminal(vc, O_RDWR|O_CLOEXEC);
184 if (fd < 0) {
185 log_error("Failed to open %s: %m", vc);
186 goto finish;
187 }
188
189 if (!is_vconsole(fd)) {
190 log_error("Device %s is not a virtual console.", vc);
191 goto finish;
192 }
193
194 utf8 = is_locale_utf8();
195
196 r = 0;
197
198 if (detect_container(NULL) <= 0) {
199 r = parse_env_file("/proc/cmdline", WHITESPACE,
200 "vconsole.keymap", &vc_keymap,
201 "vconsole.keymap.toggle", &vc_keymap_toggle,
202 "vconsole.font", &vc_font,
203 "vconsole.font.map", &vc_font_map,
204 "vconsole.font.unimap", &vc_font_unimap,
205 NULL);
206
207 if (r < 0 && r != -ENOENT)
208 log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
209 }
210
211 /* Hmm, nothing set on the kernel cmd line? Then let's
212 * try /etc/vconsole.conf */
213 if (r <= 0) {
214 r = parse_env_file("/etc/vconsole.conf", NEWLINE,
215 "KEYMAP", &vc_keymap,
216 "KEYMAP_TOGGLE", &vc_keymap_toggle,
217 "FONT", &vc_font,
218 "FONT_MAP", &vc_font_map,
219 "FONT_UNIMAP", &vc_font_unimap,
220 NULL);
221
222 if (r < 0 && r != -ENOENT)
223 log_warning("Failed to read /etc/vconsole.conf: %s", strerror(-r));
224 }
225
226 if (r <= 0) {
227 }
228
229 r = EXIT_FAILURE;
230
231 if (utf8)
232 enable_utf8(fd);
233 else
234 disable_utf8(fd);
235
236
237 if (load_keymap(vc, vc_keymap, vc_keymap_toggle, utf8, &keymap_pid) >= 0 &&
238 load_font(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid) >= 0)
239 r = EXIT_SUCCESS;
240
241 finish:
242 if (keymap_pid > 0)
243 wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid);
244
245 if (font_pid > 0)
246 wait_for_terminate_and_warn(KBD_SETFONT, font_pid);
247
248 free(vc_keymap);
249 free(vc_font);
250 free(vc_font_map);
251 free(vc_font_unimap);
252
253 if (fd >= 0)
254 close_nointr_nofail(fd);
255
256 return r;
257 }