]>
git.proxmox.com Git - systemd.git/blob - src/getty-generator/getty-generator.c
2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "alloc-util.h"
30 #include "path-util.h"
31 #include "process-util.h"
32 #include "string-util.h"
33 #include "terminal-util.h"
34 #include "unit-name.h"
38 static const char *arg_dest
= "/tmp";
40 static int add_symlink(const char *fservice
, const char *tservice
) {
47 from
= strjoina(SYSTEM_DATA_UNIT_PATH
"/", fservice
);
48 to
= strjoina(arg_dest
, "/getty.target.wants/", tservice
);
50 mkdir_parents_label(to
, 0755);
52 r
= symlink(from
, to
);
54 /* In case console=hvc0 is passed this will very likely result in EEXIST */
58 return log_error_errno(errno
, "Failed to create symlink %s: %m", to
);
64 static int add_serial_getty(const char *tty
) {
65 _cleanup_free_
char *n
= NULL
;
70 log_debug("Automatically adding serial getty for /dev/%s.", tty
);
72 r
= unit_name_from_path_instance("serial-getty", tty
, ".service", &n
);
74 return log_error_errno(r
, "Failed to generate service name: %m");
76 return add_symlink("serial-getty@.service", n
);
79 static int add_container_getty(const char *tty
) {
80 _cleanup_free_
char *n
= NULL
;
85 log_debug("Automatically adding container getty for /dev/pts/%s.", tty
);
87 r
= unit_name_from_path_instance("container-getty", tty
, ".service", &n
);
89 return log_error_errno(r
, "Failed to generate service name: %m");
91 return add_symlink("container-getty@.service", n
);
94 static int verify_tty(const char *name
) {
95 _cleanup_close_
int fd
= -1;
98 /* Some TTYs are weird and have been enumerated but don't work
99 * when you try to use them, such as classic ttyS0 and
100 * friends. Let's check that and open the device and run
103 p
= strjoina("/dev/", name
);
105 /* O_NONBLOCK is essential here, to make sure we don't wait
107 fd
= open(p
, O_RDWR
|O_NONBLOCK
|O_NOCTTY
|O_CLOEXEC
|O_NOFOLLOW
);
113 return errno
> 0 ? -errno
: -EIO
;
118 int main(int argc
, char *argv
[]) {
120 static const char virtualization_consoles
[] =
128 _cleanup_free_
char *active
= NULL
;
132 if (argc
> 1 && argc
!= 4) {
133 log_error("This program takes three or no arguments.");
140 log_set_target(LOG_TARGET_SAFE
);
141 log_parse_environment();
146 if (detect_container() > 0) {
147 _cleanup_free_
char *container_ttys
= NULL
;
149 log_debug("Automatically adding console shell.");
151 if (add_symlink("console-getty.service", "console-getty.service") < 0)
154 /* When $container_ttys is set for PID 1, spawn
155 * gettys on all ptys named therein. Note that despite
156 * the variable name we only support ptys here. */
158 r
= getenv_for_pid(1, "container_ttys", &container_ttys
);
160 const char *word
, *state
;
163 FOREACH_WORD(word
, l
, container_ttys
, state
) {
167 memcpy(tty
, word
, l
);
170 /* First strip off /dev/ if it is specified */
171 t
= path_startswith(tty
, "/dev/");
175 /* Then, make sure it's actually a pty */
176 t
= path_startswith(t
, "pts/");
180 if (add_container_getty(t
) < 0)
185 /* Don't add any further magic if we are in a container */
189 if (read_one_line_file("/sys/class/tty/console/active", &active
) >= 0) {
190 const char *word
, *state
;
193 /* Automatically add in a serial getty on all active
195 FOREACH_WORD(word
, l
, active
, state
) {
196 _cleanup_free_
char *tty
= NULL
;
198 tty
= strndup(word
, l
);
204 if (isempty(tty
) || tty_is_vc(tty
))
207 if (verify_tty(tty
) < 0)
210 /* We assume that gettys on virtual terminals are
211 * started via manual configuration and do this magic
212 * only for non-VC terminals. */
214 if (add_serial_getty(tty
) < 0)
219 /* Automatically add in a serial getty on the first
220 * virtualizer console */
221 NULSTR_FOREACH(j
, virtualization_consoles
) {
224 p
= strjoina("/sys/class/tty/", j
);
225 if (access(p
, F_OK
) < 0)
228 if (add_serial_getty(j
) < 0)