chiark / gitweb /
systemctl: try to reload daemon after enable/disable only when not running in a chroot
[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 #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 from %s to %s: %m", from, 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                 const char *tty;
126
127                 tty = strrchr(active, ' ');
128                 if (tty)
129                         tty ++;
130                 else
131                         tty = active;
132
133                 /* Automatically add in a serial getty on the kernel
134                  * console */
135                 if (isempty(tty) || tty_is_vc(tty))
136                         free(active);
137                 else {
138                         int k;
139
140                         /* We assume that gettys on virtual terminals are
141                          * started via manual configuration and do this magic
142                          * only for non-VC terminals. */
143
144                         k = add_serial_getty(tty);
145                         free(active);
146
147                         if (k < 0) {
148                                 r = EXIT_FAILURE;
149                                 goto finish;
150                         }
151                 }
152         }
153
154         /* Automatically add in a serial getty on the first
155          * virtualizer console */
156         NULSTR_FOREACH(j, virtualization_consoles) {
157                 char *p;
158                 int k;
159
160                 if (asprintf(&p, "/sys/class/tty/%s", j) < 0) {
161                         log_oom();
162                         r = EXIT_FAILURE;
163                         goto finish;
164                 }
165
166                 k = access(p, F_OK);
167                 free(p);
168
169                 if (k < 0)
170                         continue;
171
172                 k = add_serial_getty(j);
173                 if (k < 0) {
174                         r = EXIT_FAILURE;
175                         goto finish;
176                 }
177         }
178
179 finish:
180         return r;
181 }