]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/getty-generator/getty-generator.c
getty-generator: fix segfault when $container_ttys is not set
[thirdparty/systemd.git] / src / getty-generator / getty-generator.c
CommitLineData
2a796654
LP
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
5430f7f2
LP
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
2a796654
LP
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
5430f7f2 16 Lesser General Public License for more details.
2a796654 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
2a796654
LP
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"
49e942b2 28#include "mkdir.h"
2a796654 29#include "unit-name.h"
5dc4c17f 30#include "virt.h"
a5c32cff 31#include "fileio.h"
1d97ff7d 32#include "path-util.h"
2a796654 33
6a39419f 34static const char *arg_dest = "/tmp";
2a796654
LP
35
36static int add_symlink(const char *fservice, const char *tservice) {
f85fc845 37 _cleanup_free_ char *from = NULL, *to = NULL;
2a796654
LP
38 int r;
39
4dc380d1
LP
40 assert(fservice);
41 assert(tservice);
42
07719a21 43 from = strappend(SYSTEM_DATA_UNIT_PATH "/", fservice);
f85fc845
LP
44 if (!from)
45 return log_oom();
2a796654 46
f85fc845
LP
47 to = strjoin(arg_dest,"/getty.target.wants/", tservice, NULL);
48 if (!to)
49 return log_oom();
2a796654 50
d2e54fae 51 mkdir_parents_label(to, 0755);
2a796654 52
a17b785b
LP
53 r = symlink(from, to);
54 if (r < 0) {
55 if (errno == EEXIST)
3c20189a 56 /* In case console=hvc0 is passed this will very likely result in EEXIST */
f85fc845 57 return 0;
a17b785b 58 else {
c79bb9e4 59 log_error("Failed to create symlink %s: %m", to);
f85fc845 60 return -errno;
a17b785b 61 }
2a796654
LP
62 }
63
f85fc845 64 return 0;
2a796654
LP
65}
66
4dc380d1 67static int add_serial_getty(const char *tty) {
f85fc845 68 _cleanup_free_ char *n = NULL;
4dc380d1
LP
69
70 assert(tty);
71
72 log_debug("Automatically adding serial getty for /dev/%s.", tty);
73
74 n = unit_name_replace_instance("serial-getty@.service", tty);
0d0f0c50
SL
75 if (!n)
76 return log_oom();
4dc380d1 77
f85fc845 78 return add_symlink("serial-getty@.service", n);
4dc380d1
LP
79}
80
1d97ff7d
LP
81static int add_container_getty(const char *tty) {
82 _cleanup_free_ char *n = NULL;
83
84 assert(tty);
85
86 log_debug("Automatically adding container getty for /dev/pts/%s.", tty);
87
88 n = unit_name_replace_instance("container-getty@.service", tty);
89 if (!n)
90 return log_oom();
91
92 return add_symlink("container-getty@.service", n);
93}
94
2a796654 95int main(int argc, char *argv[]) {
3c20189a
LP
96
97 static const char virtualization_consoles[] =
98 "hvc0\0"
99 "xvc0\0"
100 "hvsi0\0";
101
f85fc845 102 _cleanup_free_ char *active = NULL;
3c20189a 103 const char *j;
1d97ff7d 104 int r;
2a796654 105
07719a21
LP
106 if (argc > 1 && argc != 4) {
107 log_error("This program takes three or no arguments.");
2a796654
LP
108 return EXIT_FAILURE;
109 }
110
07719a21
LP
111 if (argc > 1)
112 arg_dest = argv[1];
113
a6903061 114 log_set_target(LOG_TARGET_SAFE);
2a796654
LP
115 log_parse_environment();
116 log_open();
117
4c12626c
LP
118 umask(0022);
119
2a796654 120 if (detect_container(NULL) > 0) {
1d97ff7d
LP
121 _cleanup_free_ char *container_ttys = NULL;
122
6705c2df 123 log_debug("Automatically adding console shell.");
2a796654 124
337eebb9 125 if (add_symlink("console-getty.service", "console-getty.service") < 0)
f85fc845 126 return EXIT_FAILURE;
2a796654 127
1d97ff7d
LP
128 /* When $container_ttys is set for PID 1, spawn
129 * gettys on all ptys named therein. Note that despite
130 * the variable name we only support ptys here. */
131
132 r = getenv_for_pid(1, "container_ttys", &container_ttys);
207d1d09 133 if (r > 0) {
1d97ff7d
LP
134 char *w, *state;
135 size_t l;
136
137 FOREACH_WORD(w, l, container_ttys, state) {
138 const char *t;
139 char tty[l + 1];
140
141 memcpy(tty, w, l);
142 tty[l] = 0;
143
144 /* First strip off /dev/ if it is specified */
145 t = path_startswith(tty, "/dev/");
146 if (!t)
147 t = tty;
148
149 /* Then, make sure it's actually a pty */
150 t = path_startswith(tty, "pts/");
151 if (!t)
152 continue;
153
154 if (add_container_getty(t) < 0)
155 return EXIT_FAILURE;
156 }
157 }
158
2a796654 159 /* Don't add any further magic if we are in a container */
f85fc845 160 return EXIT_SUCCESS;
2a796654
LP
161 }
162
163 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
39f0570d
MM
164 char *w, *state;
165 size_t l;
166
167 /* Automatically add in a serial getty on all active
168 * kernel consoles */
169 FOREACH_WORD(w, l, active, state) {
f85fc845 170 _cleanup_free_ char *tty = NULL;
2a796654 171
39f0570d
MM
172 tty = strndup(w, l);
173 if (!tty) {
f85fc845
LP
174 log_oom();
175 return EXIT_FAILURE;
39f0570d
MM
176 }
177
f85fc845 178 if (isempty(tty) || tty_is_vc(tty))
39f0570d 179 continue;
39f0570d 180
2a796654
LP
181 /* We assume that gettys on virtual terminals are
182 * started via manual configuration and do this magic
183 * only for non-VC terminals. */
184
f85fc845
LP
185 if (add_serial_getty(tty) < 0)
186 return EXIT_FAILURE;
3c20189a 187 }
2a796654
LP
188 }
189
190 /* Automatically add in a serial getty on the first
191 * virtualizer console */
3c20189a 192 NULSTR_FOREACH(j, virtualization_consoles) {
f85fc845 193 _cleanup_free_ char *p = NULL;
2a796654 194
f85fc845
LP
195 p = strappend("/sys/class/tty/", j);
196 if (!p) {
0d0f0c50 197 log_oom();
f85fc845 198 return EXIT_FAILURE;
3c20189a 199 }
980fc73d 200
f85fc845 201 if (access(p, F_OK) < 0)
3c20189a 202 continue;
980fc73d 203
f85fc845
LP
204 if (add_serial_getty(j) < 0)
205 return EXIT_FAILURE;
2a796654
LP
206 }
207
f85fc845 208 return EXIT_SUCCESS;
2a796654 209}