]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/getty-generator/getty-generator.c
log: remove LOG_TARGET_SAFE pseudo log target
[thirdparty/systemd.git] / src / getty-generator / getty-generator.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
2a796654
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
2a796654
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
2a796654 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
2a796654
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
2a796654 21#include <errno.h>
54340751 22#include <fcntl.h>
07630cea
LP
23#include <string.h>
24#include <unistd.h>
2a796654 25
b5efdb8a 26#include "alloc-util.h"
3ffd4af2 27#include "fd-util.h"
07630cea 28#include "fileio.h"
2a796654 29#include "log.h"
49e942b2 30#include "mkdir.h"
1d97ff7d 31#include "path-util.h"
0b452006 32#include "process-util.h"
07630cea 33#include "string-util.h"
288a74cc 34#include "terminal-util.h"
07630cea
LP
35#include "unit-name.h"
36#include "util.h"
37#include "virt.h"
2a796654 38
6a39419f 39static const char *arg_dest = "/tmp";
2a796654
LP
40
41static int add_symlink(const char *fservice, const char *tservice) {
f5650614 42 char *from, *to;
2a796654
LP
43 int r;
44
4dc380d1
LP
45 assert(fservice);
46 assert(tservice);
47
63c372cb
LP
48 from = strjoina(SYSTEM_DATA_UNIT_PATH "/", fservice);
49 to = strjoina(arg_dest, "/getty.target.wants/", tservice);
2a796654 50
d2e54fae 51 mkdir_parents_label(to, 0755);
2a796654 52
a17b785b
LP
53 r = symlink(from, to);
54 if (r < 0) {
7410616c 55 /* In case console=hvc0 is passed this will very likely result in EEXIST */
a17b785b 56 if (errno == EEXIST)
f85fc845 57 return 0;
7410616c
LP
58
59 return log_error_errno(errno, "Failed to create symlink %s: %m", to);
2a796654
LP
60 }
61
f85fc845 62 return 0;
2a796654
LP
63}
64
4dc380d1 65static int add_serial_getty(const char *tty) {
f85fc845 66 _cleanup_free_ char *n = NULL;
7410616c 67 int r;
4dc380d1
LP
68
69 assert(tty);
70
71 log_debug("Automatically adding serial getty for /dev/%s.", tty);
72
7410616c
LP
73 r = unit_name_from_path_instance("serial-getty", tty, ".service", &n);
74 if (r < 0)
75 return log_error_errno(r, "Failed to generate service name: %m");
4dc380d1 76
f85fc845 77 return add_symlink("serial-getty@.service", n);
4dc380d1
LP
78}
79
1d97ff7d
LP
80static int add_container_getty(const char *tty) {
81 _cleanup_free_ char *n = NULL;
7410616c 82 int r;
1d97ff7d
LP
83
84 assert(tty);
85
86 log_debug("Automatically adding container getty for /dev/pts/%s.", tty);
87
7410616c
LP
88 r = unit_name_from_path_instance("container-getty", tty, ".service", &n);
89 if (r < 0)
90 return log_error_errno(r, "Failed to generate service name: %m");
1d97ff7d
LP
91
92 return add_symlink("container-getty@.service", n);
93}
94
54340751
LP
95static int verify_tty(const char *name) {
96 _cleanup_close_ int fd = -1;
97 const char *p;
98
99 /* Some TTYs are weird and have been enumerated but don't work
100 * when you try to use them, such as classic ttyS0 and
101 * friends. Let's check that and open the device and run
102 * isatty() on it. */
103
63c372cb 104 p = strjoina("/dev/", name);
54340751
LP
105
106 /* O_NONBLOCK is essential here, to make sure we don't wait
107 * for DCD */
108 fd = open(p, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW);
109 if (fd < 0)
110 return -errno;
111
112 errno = 0;
113 if (isatty(fd) <= 0)
f5e5c28f 114 return errno > 0 ? -errno : -EIO;
54340751
LP
115
116 return 0;
117}
118
2a796654 119int main(int argc, char *argv[]) {
3c20189a
LP
120
121 static const char virtualization_consoles[] =
122 "hvc0\0"
123 "xvc0\0"
07901fc1
HB
124 "hvsi0\0"
125 "sclp_line0\0"
fc6c7fe9
HB
126 "ttysclp0\0"
127 "3270!tty1\0";
3c20189a 128
f85fc845 129 _cleanup_free_ char *active = NULL;
3c20189a 130 const char *j;
1d97ff7d 131 int r;
2a796654 132
07719a21
LP
133 if (argc > 1 && argc != 4) {
134 log_error("This program takes three or no arguments.");
2a796654
LP
135 return EXIT_FAILURE;
136 }
137
07719a21
LP
138 if (argc > 1)
139 arg_dest = argv[1];
140
6c347d50
LP
141 log_set_prohibit_ipc(true);
142 log_set_target(LOG_TARGET_AUTO);
2a796654
LP
143 log_parse_environment();
144 log_open();
145
4c12626c
LP
146 umask(0022);
147
75f86906 148 if (detect_container() > 0) {
1d97ff7d
LP
149 _cleanup_free_ char *container_ttys = NULL;
150
6705c2df 151 log_debug("Automatically adding console shell.");
2a796654 152
337eebb9 153 if (add_symlink("console-getty.service", "console-getty.service") < 0)
f85fc845 154 return EXIT_FAILURE;
2a796654 155
1d97ff7d
LP
156 /* When $container_ttys is set for PID 1, spawn
157 * gettys on all ptys named therein. Note that despite
158 * the variable name we only support ptys here. */
159
160 r = getenv_for_pid(1, "container_ttys", &container_ttys);
207d1d09 161 if (r > 0) {
a2a5291b 162 const char *word, *state;
1d97ff7d
LP
163 size_t l;
164
a2a5291b 165 FOREACH_WORD(word, l, container_ttys, state) {
1d97ff7d
LP
166 const char *t;
167 char tty[l + 1];
168
a2a5291b 169 memcpy(tty, word, l);
1d97ff7d
LP
170 tty[l] = 0;
171
172 /* First strip off /dev/ if it is specified */
173 t = path_startswith(tty, "/dev/");
174 if (!t)
175 t = tty;
176
177 /* Then, make sure it's actually a pty */
3fa5dd6d 178 t = path_startswith(t, "pts/");
1d97ff7d
LP
179 if (!t)
180 continue;
181
182 if (add_container_getty(t) < 0)
183 return EXIT_FAILURE;
184 }
185 }
186
2a796654 187 /* Don't add any further magic if we are in a container */
f85fc845 188 return EXIT_SUCCESS;
2a796654
LP
189 }
190
191 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
a2a5291b 192 const char *word, *state;
39f0570d
MM
193 size_t l;
194
195 /* Automatically add in a serial getty on all active
196 * kernel consoles */
a2a5291b 197 FOREACH_WORD(word, l, active, state) {
f85fc845 198 _cleanup_free_ char *tty = NULL;
2a796654 199
a2a5291b 200 tty = strndup(word, l);
39f0570d 201 if (!tty) {
f85fc845
LP
202 log_oom();
203 return EXIT_FAILURE;
39f0570d
MM
204 }
205
54194afb
AJ
206 /* We assume that gettys on virtual terminals are
207 * started via manual configuration and do this magic
208 * only for non-VC terminals. */
209
f85fc845 210 if (isempty(tty) || tty_is_vc(tty))
39f0570d 211 continue;
39f0570d 212
54340751
LP
213 if (verify_tty(tty) < 0)
214 continue;
215
f85fc845
LP
216 if (add_serial_getty(tty) < 0)
217 return EXIT_FAILURE;
3c20189a 218 }
2a796654
LP
219 }
220
221 /* Automatically add in a serial getty on the first
222 * virtualizer console */
3c20189a 223 NULSTR_FOREACH(j, virtualization_consoles) {
f5650614 224 char *p;
980fc73d 225
63c372cb 226 p = strjoina("/sys/class/tty/", j);
f85fc845 227 if (access(p, F_OK) < 0)
3c20189a 228 continue;
980fc73d 229
f85fc845
LP
230 if (add_serial_getty(j) < 0)
231 return EXIT_FAILURE;
2a796654
LP
232 }
233
f85fc845 234 return EXIT_SUCCESS;
2a796654 235}