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