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