]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/getty-generator/getty-generator.c
getty-generator: Enable getty on all active serial consoles.
[thirdparty/systemd.git] / src / getty-generator / getty-generator.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 Lennart Poettering
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 <string.h>
23 #include <errno.h>
24 #include <unistd.h>
25
26 #include "log.h"
27 #include "util.h"
28 #include "mkdir.h"
29 #include "unit-name.h"
30 #include "virt.h"
31 #include "fileio.h"
32
33 static const char *arg_dest = "/tmp";
34
35 static int add_symlink(const char *fservice, const char *tservice) {
36 char *from = NULL, *to = NULL;
37 int r;
38
39 assert(fservice);
40 assert(tservice);
41
42 from = strappend(SYSTEM_DATA_UNIT_PATH "/", fservice);
43 to = strjoin(arg_dest,"/getty.target.wants/", tservice, NULL);
44
45 if (!from || !to) {
46 r = log_oom();
47 goto finish;
48 }
49
50 mkdir_parents_label(to, 0755);
51
52 r = symlink(from, to);
53 if (r < 0) {
54 if (errno == EEXIST)
55 /* In case console=hvc0 is passed this will very likely result in EEXIST */
56 r = 0;
57 else {
58 log_error("Failed to create symlink %s: %m", to);
59 r = -errno;
60 }
61 }
62
63 finish:
64
65 free(from);
66 free(to);
67
68 return r;
69 }
70
71 static int add_serial_getty(const char *tty) {
72 char *n;
73 int r;
74
75 assert(tty);
76
77 log_debug("Automatically adding serial getty for /dev/%s.", tty);
78
79 n = unit_name_replace_instance("serial-getty@.service", tty);
80 if (!n)
81 return log_oom();
82
83 r = add_symlink("serial-getty@.service", n);
84 free(n);
85
86 return r;
87 }
88
89 int main(int argc, char *argv[]) {
90
91 static const char virtualization_consoles[] =
92 "hvc0\0"
93 "xvc0\0"
94 "hvsi0\0";
95
96 int r = EXIT_SUCCESS;
97 char *active;
98 const char *j;
99
100 if (argc > 1 && argc != 4) {
101 log_error("This program takes three or no arguments.");
102 return EXIT_FAILURE;
103 }
104
105 if (argc > 1)
106 arg_dest = argv[1];
107
108 log_set_target(LOG_TARGET_SAFE);
109 log_parse_environment();
110 log_open();
111
112 umask(0022);
113
114 if (detect_container(NULL) > 0) {
115 log_debug("Automatically adding console shell.");
116
117 if (add_symlink("console-getty.service", "console-getty.service") < 0)
118 r = EXIT_FAILURE;
119
120 /* Don't add any further magic if we are in a container */
121 goto finish;
122 }
123
124 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
125 char *w, *state;
126 size_t l;
127
128 /* Automatically add in a serial getty on all active
129 * kernel consoles */
130 FOREACH_WORD(w, l, active, state) {
131 char *tty;
132 int k;
133
134 tty = strndup(w, l);
135 if (!tty) {
136 log_oom();
137 free(active);
138 r = EXIT_FAILURE;
139 goto finish;
140 }
141
142 if (isempty(tty) || tty_is_vc(tty)) {
143 free(tty);
144 continue;
145 }
146
147 /* We assume that gettys on virtual terminals are
148 * started via manual configuration and do this magic
149 * only for non-VC terminals. */
150
151 k = add_serial_getty(tty);
152
153 if (k < 0) {
154 free(tty);
155 free(active);
156 r = EXIT_FAILURE;
157 goto finish;
158 }
159 }
160 free(active);
161 }
162
163 /* Automatically add in a serial getty on the first
164 * virtualizer console */
165 NULSTR_FOREACH(j, virtualization_consoles) {
166 char *p;
167 int k;
168
169 if (asprintf(&p, "/sys/class/tty/%s", j) < 0) {
170 log_oom();
171 r = EXIT_FAILURE;
172 goto finish;
173 }
174
175 k = access(p, F_OK);
176 free(p);
177
178 if (k < 0)
179 continue;
180
181 k = add_serial_getty(j);
182 if (k < 0) {
183 r = EXIT_FAILURE;
184 goto finish;
185 }
186 }
187
188 finish:
189 return r;
190 }