getty-generator.c revision 1d97ff7dd71902a5604c2fed8964925d54e09de9
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/***
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright 2010 Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is distributed in the hope that it will be useful, but
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Lesser General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering***/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering#include <string.h>
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering#include <errno.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <unistd.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "log.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "mkdir.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "unit-name.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "virt.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "fileio.h"
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering#include "path-util.h"
24882e06c135584f16f31ba8a00fecde8b7f6fadLennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poetteringstatic const char *arg_dest = "/tmp";
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poetteringstatic int add_symlink(const char *fservice, const char *tservice) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ char *from = NULL, *to = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(fservice);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert(tservice);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering from = strappend(SYSTEM_DATA_UNIT_PATH "/", fservice);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!from)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return log_oom();
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering to = strjoin(arg_dest,"/getty.target.wants/", tservice, NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!to)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return log_oom();
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering mkdir_parents_label(to, 0755);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = symlink(from, to);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (errno == EEXIST)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* In case console=hvc0 is passed this will very likely result in EEXIST */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else {
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering log_error("Failed to create symlink %s: %m", to);
4f10118016f9b2fd7e1d26c9ef7d91eb33fba694Lennart Poettering return -errno;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int add_serial_getty(const char *tty) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_free_ char *n = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(tty);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug("Automatically adding serial getty for /dev/%s.", tty);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering n = unit_name_replace_instance("serial-getty@.service", tty);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!n)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return log_oom();
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return add_symlink("serial-getty@.service", n);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int add_container_getty(const char *tty) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_free_ char *n = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(tty);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug("Automatically adding container getty for /dev/pts/%s.", tty);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering n = unit_name_replace_instance("container-getty@.service", tty);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!n)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return log_oom();
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return add_symlink("container-getty@.service", n);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint main(int argc, char *argv[]) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering static const char virtualization_consoles[] =
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "hvc0\0"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "xvc0\0"
a1e58e8ee1c84b633d6d6d651d5328d4dd4eba5bLennart Poettering "hvsi0\0";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_free_ char *active = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering const char *j;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (argc > 1 && argc != 4) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("This program takes three or no arguments.");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return EXIT_FAILURE;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (argc > 1)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering arg_dest = argv[1];
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_set_target(LOG_TARGET_SAFE);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_parse_environment();
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_open();
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering umask(0022);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (detect_container(NULL) > 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_free_ char *container_ttys = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug("Automatically adding console shell.");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (add_symlink("console-getty.service", "console-getty.service") < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return EXIT_FAILURE;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* When $container_ttys is set for PID 1, spawn
920b52e4909d9dc812817fd8b82f83ca23a11c91Thomas Hindoe Paaboel Andersen * gettys on all ptys named therein. Note that despite
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * the variable name we only support ptys here. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = getenv_for_pid(1, "container_ttys", &container_ttys);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r >= 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering char *w, *state;
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen size_t l;
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen FOREACH_WORD(w, l, container_ttys, state) {
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen const char *t;
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen char tty[l + 1];
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcpy(tty, w, l);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering tty[l] = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* First strip off /dev/ if it is specified */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering t = path_startswith(tty, "/dev/");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!t)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering t = tty;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Then, make sure it's actually a pty */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering t = path_startswith(tty, "pts/");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!t)
b2c23da8cea1987a1a329f5a964d3299b7ca7890Lennart Poettering continue;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (add_container_getty(t) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return EXIT_FAILURE;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Don't add any further magic if we are in a container */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return EXIT_SUCCESS;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char *w, *state;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size_t l;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Automatically add in a serial getty on all active
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering * kernel consoles */
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering FOREACH_WORD(w, l, active, state) {
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering _cleanup_free_ char *tty = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering tty = strndup(w, l);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!tty) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_oom();
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return EXIT_FAILURE;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (isempty(tty) || tty_is_vc(tty))
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack continue;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* We assume that gettys on virtual terminals are
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * started via manual configuration and do this magic
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack * only for non-VC terminals. */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (add_serial_getty(tty) < 0)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return EXIT_FAILURE;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* Automatically add in a serial getty on the first
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * virtualizer console */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering NULSTR_FOREACH(j, virtualization_consoles) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ char *p = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering p = strappend("/sys/class/tty/", j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!p) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_oom();
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return EXIT_FAILURE;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (access(p, F_OK) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering continue;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (add_serial_getty(j) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return EXIT_FAILURE;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return EXIT_SUCCESS;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering