summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/auto-serial-getty.c189
-rw-r--r--src/main.c29
-rw-r--r--src/manager.c19
-rw-r--r--src/manager.h4
-rw-r--r--src/special.h2
-rw-r--r--src/target.c45
6 files changed, 97 insertions, 191 deletions
diff --git a/src/auto-serial-getty.c b/src/auto-serial-getty.c
deleted file mode 100644
index 355cdfd6a..000000000
--- a/src/auto-serial-getty.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <dbus/dbus.h>
-
-#include "util.h"
-#include "log.h"
-#include "dbus-common.h"
-
-static int spawn_getty(DBusConnection *bus, const char *console) {
- DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- const char *fail = "fail";
- char *name;
- int r = -EIO;
-
- dbus_error_init(&error);
-
- assert(bus);
- assert(console);
-
- /* FIXME: we probably should escape the tty name properly here */
- if (asprintf(&name, "serial-getty@%s.service", console) < 0)
- return -ENOMEM;
-
- if (!(m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit"))) {
- log_error("Could not allocate message.");
- goto finish;
- }
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &fail,
- DBUS_TYPE_INVALID)) {
- log_error("Could not attach target and flag information to message.");
- goto finish;
- }
-
- if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
- log_error("Failed to start unit: %s", bus_error_message(&error));
- goto finish;
- }
-
- r = 0;
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- free(name);
-
- return r;
-}
-
-static int parse_proc_cmdline_word(const char *word, char **console) {
- assert(word);
-
- if (startswith(word, "console=")) {
- const char *k;
- size_t l;
- char *w = NULL;
-
- k = word + 8;
- l = strcspn(k, ",");
-
- if (l < 4 ||
- !startswith(k, "tty") ||
- k[3+strspn(k+3, "0123456789")] != 0) {
-
- if (!(w = strndup(k, l)))
- return -ENOMEM;
-
- }
-
- free(*console);
- *console = w;
- }
-
- return 0;
-}
-
-static int parse_proc_cmdline(char **console) {
- char *line;
- int r;
- char *w;
- size_t l;
- char *state;
-
- assert(console);
-
- if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
- char *word;
-
- if (!(word = strndup(w, l))) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = parse_proc_cmdline_word(word, console);
- free(word);
-
- if (r < 0)
- goto finish;
- }
-
- r = 0;
-
-finish:
- free(line);
- return r;
-}
-
-int main(int argc, char *argv[]) {
- DBusError error;
- int r = 1;
- char *console = NULL;
- DBusConnection *bus = NULL;
-
- dbus_error_init(&error);
-
- if (argc > 1) {
- log_error("This program does not take arguments.");
- return 1;
- }
-
- log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
- log_parse_environment();
- log_open();
-
- if (bus_connect(DBUS_BUS_SYSTEM, &bus, NULL, &error) < 0) {
- log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
- goto finish;
- }
-
- if (parse_proc_cmdline(&console) < 0)
- goto finish;
-
- if (console)
- if (spawn_getty(bus, console) < 0)
- goto finish;
-
- r = 0;
-
-finish:
- free(console);
-
- if (bus) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
-
- dbus_shutdown();
-
- return r;
-}
diff --git a/src/main.c b/src/main.c
index f1fa56911..53a455b50 100644
--- a/src/main.c
+++ b/src/main.c
@@ -66,6 +66,7 @@ static bool arg_show_status = true;
static bool arg_sysv_console = true;
static bool arg_mount_auto = true;
static bool arg_swap_auto = true;
+static char *arg_console = NULL;
static FILE* serialization = NULL;
@@ -335,6 +336,26 @@ static int parse_proc_cmdline_word(const char *word) {
"systemd.log_color=0|1 Highlight important log messages\n"
"systemd.log_location=0|1 Include code location in log messages\n");
+ } else if (startswith(word, "console=")) {
+ const char *k;
+ size_t l;
+ char *w = NULL;
+
+ k = word + 8;
+ l = strcspn(k, ",");
+
+ /* Ignore the console setting if set to a VT */
+ if (l < 4 ||
+ !startswith(k, "tty") ||
+ k[3+strspn(k+3, "0123456789")] != 0) {
+
+ if (!(w = strndup(k, l)))
+ return -ENOMEM;
+ }
+
+ free(arg_console);
+ arg_console = w;
+
} else if (streq(word, "quiet")) {
arg_show_status = false;
arg_sysv_console = false;
@@ -993,6 +1014,9 @@ int main(int argc, char *argv[]) {
m->mount_auto = arg_mount_auto;
m->swap_auto = arg_swap_auto;
+ if (arg_console)
+ manager_set_console(m, arg_console);
+
if ((r = manager_startup(m, serialization, fds)) < 0)
log_error("Failed to fully start up daemon: %s", strerror(-r));
@@ -1090,9 +1114,12 @@ finish:
manager_free(m);
free(arg_default_unit);
+ free(arg_console);
dbus_shutdown();
+ label_finish();
+
if (reexecute) {
const char *args[15];
unsigned i = 0;
@@ -1157,7 +1184,5 @@ finish:
if (getpid() == 1)
freeze();
- label_finish();
-
return retval;
}
diff --git a/src/manager.c b/src/manager.c
index 09b2c789e..0afc99243 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -112,6 +112,8 @@ static int manager_setup_notify(Manager *m) {
if (!(m->notify_socket = strdup(sa.un.sun_path+1)))
return -ENOMEM;
+ log_debug("Using notification socket %s", m->notify_socket);
+
return 0;
}
@@ -447,6 +449,7 @@ void manager_free(Manager *m) {
#endif
free(m->notify_socket);
+ free(m->console);
lookup_paths_free(&m->lookup_paths);
strv_free(m->environment);
@@ -2553,6 +2556,22 @@ void manager_reset_maintenance(Manager *m) {
unit_reset_maintenance(u);
}
+int manager_set_console(Manager *m, const char *console) {
+ char *c;
+
+ assert(m);
+
+ if (!(c = strdup(console)))
+ return -ENOMEM;
+
+ free(m->console);
+ m->console = c;
+
+ log_debug("Using kernel console %s", c);
+
+ return 0;
+}
+
static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {
[MANAGER_SYSTEM] = "system",
[MANAGER_SESSION] = "session"
diff --git a/src/manager.h b/src/manager.h
index e3c6db23b..6186cb233 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -140,6 +140,8 @@ struct Manager {
dual_timestamp startup_timestamp;
+ char *console;
+
/* Data specific to the device subsystem */
struct udev* udev;
struct udev_monitor* udev_monitor;
@@ -237,6 +239,8 @@ unsigned manager_dispatch_load_queue(Manager *m);
unsigned manager_dispatch_run_queue(Manager *m);
unsigned manager_dispatch_dbus_queue(Manager *m);
+int manager_set_console(Manager *m, const char *console);
+
int manager_loop(Manager *m);
void manager_dispatch_bus_name_owner_changed(Manager *m, const char *name, const char* old_owner, const char *new_owner);
diff --git a/src/special.h b/src/special.h
index 7bf207053..0cc5cc647 100644
--- a/src/special.h
+++ b/src/special.h
@@ -59,6 +59,8 @@
#define SPECIAL_POWEROFF_TARGET "poweroff.target"
#define SPECIAL_REBOOT_TARGET "reboot.target"
#define SPECIAL_DBUS_SERVICE "dbus.service"
+#define SPECIAL_GETTY_TARGET "getty.target"
+#define SPECIAL_SERIAL_GETTY_SERVICE "serial-getty@.service"
#ifndef SPECIAL_SYSLOG_SERVICE
#define SPECIAL_SYSLOG_SERVICE "syslog.service"
diff --git a/src/target.c b/src/target.c
index c7285fa73..c350d8fa1 100644
--- a/src/target.c
+++ b/src/target.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <signal.h>
+#include <unistd.h>
#include "unit.h"
#include "target.h"
@@ -28,6 +29,7 @@
#include "log.h"
#include "dbus-target.h"
#include "special.h"
+#include "unit-name.h"
static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
[TARGET_DEAD] = UNIT_INACTIVE,
@@ -76,6 +78,46 @@ static int target_add_default_dependencies(Target *t) {
return 0;
}
+static int target_add_getty_dependencies(Target *t) {
+ char *n;
+ int r;
+
+ assert(t);
+
+ if (!unit_has_name(UNIT(t), SPECIAL_GETTY_TARGET))
+ return 0;
+
+ /* Automatically add in a serial getty on the kernel
+ * console */
+ if (t->meta.manager->console) {
+ log_debug("Automatically adding serial getty for %s", t->meta.manager->console);
+ if (!(n = unit_name_replace_instance(SPECIAL_SERIAL_GETTY_SERVICE, t->meta.manager->console)))
+ return -ENOMEM;
+
+ r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_WANTS, n, NULL, true);
+ free(n);
+
+ if (r < 0)
+ return r;
+ }
+
+ /* Automatically add in a serial getty on the first
+ * virtualizer console */
+ if (access("/sys/class/tty/hvc0", F_OK) == 0) {
+ log_debug("Automatic adding serial getty for hvc0");
+ if (!(n = unit_name_replace_instance(SPECIAL_SERIAL_GETTY_SERVICE, "hvc0")))
+ return -ENOMEM;
+
+ r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_WANTS, n, NULL, true);
+ free(n);
+
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
static int target_load(Unit *u) {
Target *t = TARGET(u);
int r;
@@ -90,6 +132,9 @@ static int target_load(Unit *u) {
if (u->meta.default_dependencies)
if ((r = target_add_default_dependencies(t)) < 0)
return r;
+
+ if ((r = target_add_getty_dependencies(t)) < 0)
+ return r;
}
return 0;