summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorViorel Suman <viorel.suman@intel.com>2016-03-09 17:50:10 +0200
committerViorel Suman <viorel.suman@intel.com>2016-03-17 21:00:15 +0200
commitcaafe5c6204bc2066e6201a67ecd7cd1b3f8d015 (patch)
treeee1f184b3655bfbfdf739bf1ce1f5e4412fca4ca /init
parent371e7ea170d749489a0eb7085347f58b7be63734 (diff)
downloadcore-caafe5c6204bc2066e6201a67ecd7cd1b3f8d015.tar.gz
core-caafe5c6204bc2066e6201a67ecd7cd1b3f8d015.tar.bz2
core-caafe5c6204bc2066e6201a67ecd7cd1b3f8d015.zip
Enable multiple consoles
This CL allows enabling of multiple consoles. The expected format of "androidboot.console" kernel parameter is a list of available consoles, as follows: androidboot.console=tty0:ttyS0 A service can be mapped to a specific console by providing the optional argument, IE "tty0", to "console" service attribute as follows: service fbconsole /system/bin/sh class core console tty0 disabled user shell group shell log readproc seclabel u:r:shell:s0 Bug: None Change-Id: I3f8556425c8651bd121995869700f18b23365d55 Tracked-On: https://jira01.devtools.intel.com/browse/BP-289
Diffstat (limited to 'init')
-rw-r--r--init/init.cpp48
-rw-r--r--init/init.h5
-rw-r--r--init/readme.txt5
-rw-r--r--init/service.cpp13
-rw-r--r--init/service.h1
5 files changed, 33 insertions, 39 deletions
diff --git a/init/init.cpp b/init/init.cpp
index bac27df88..704597d2d 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -74,8 +74,7 @@ static int property_triggers_enabled = 0;
static char qemu[32];
-int have_console;
-std::string console_name = "/dev/console";
+std::vector<std::string> console_names;
static time_t process_needs_restart;
const char *ENV[32];
@@ -298,38 +297,23 @@ static int keychord_init_action(const std::vector<std::string>& args)
static int console_init_action(const std::vector<std::string>& args)
{
- std::string console = property_get("ro.boot.console");
- if (!console.empty()) {
- console_name = "/dev/" + console;
- }
-
- int fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC);
- if (fd >= 0)
- have_console = 1;
- close(fd);
-
- fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
- if (fd >= 0) {
- const char *msg;
- msg = "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n" // console is 40 cols x 30 lines
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- " A N D R O I D ";
- write(fd, msg, strlen(msg));
- close(fd);
+ std::vector<std::string> consoles;
+ std::string c_prop = property_get("ro.boot.console");
+ if (c_prop.empty()) {
+ // Property is missing, so check the system console by default.
+ consoles.emplace_back(DEFAULT_CONSOLE);
+ } else {
+ consoles = android::base::Split(c_prop, ":");
}
+ for (const auto& c : consoles) {
+ std::string console = "/dev/" + c;
+ int fd = open(console.c_str(), O_RDWR | O_CLOEXEC);
+ if (fd != -1) {
+ console_names.emplace_back(c);
+ close(fd);
+ }
+ }
return 0;
}
diff --git a/init/init.h b/init/init.h
index b6a095b94..c844489ac 100644
--- a/init/init.h
+++ b/init/init.h
@@ -18,16 +18,17 @@
#define _INIT_INIT_H
#include <string>
+#include <vector>
class Action;
class Service;
#define COMMAND_RETRY_TIMEOUT 5
+#define DEFAULT_CONSOLE "console"
extern const char *ENV[32];
extern bool waiting_for_exec;
-extern int have_console;
-extern std::string console_name;
+extern std::vector<std::string> console_names;
extern struct selabel_handle *sehandle;
extern struct selabel_handle *sehandle_prop;
diff --git a/init/readme.txt b/init/readme.txt
index ef85ccf1f..7d453c674 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -115,6 +115,11 @@ Options
Options are modifiers to services. They affect how and when init
runs the service.
+console [<console>]
+ This service needs a console. The optional second parameter chooses a
+ specific console instead of the default "/dev/console". The leading "/dev/"
+ should be omitted, so "/dev/tty0" would be specified as just "console tty0".
+
critical
This is a device-critical service. If it exits more than four times in
four minutes, the device will reboot into recovery mode.
diff --git a/init/service.cpp b/init/service.cpp
index bdecc324f..e7bbf7b20 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -172,6 +172,7 @@ bool Service::HandleClass(const std::vector<std::string>& args, std::string* err
bool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) {
flags_ |= SVC_CONSOLE;
+ console_ = args.size() > 1 ? args[1] : DEFAULT_CONSOLE;
return true;
}
@@ -282,7 +283,7 @@ Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
static const Map option_handlers = {
{"class", {1, 1, &Service::HandleClass}},
- {"console", {0, 0, &Service::HandleConsole}},
+ {"console", {0, 1, &Service::HandleConsole}},
{"critical", {0, 0, &Service::HandleCritical}},
{"disabled", {0, 0, &Service::HandleDisabled}},
{"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
@@ -329,7 +330,7 @@ bool Service::Start(const std::vector<std::string>& dynamic_args) {
}
bool needs_console = (flags_ & SVC_CONSOLE);
- if (needs_console && !have_console) {
+ if (needs_console && console_names.empty()) {
ERROR("service '%s' requires console\n", name_.c_str());
flags_ |= SVC_DISABLED;
return false;
@@ -606,10 +607,12 @@ void Service::ZapStdio() const {
}
void Service::OpenConsole() const {
- int fd;
- if ((fd = open(console_name.c_str(), O_RDWR)) < 0) {
- fd = open("/dev/null", O_RDWR);
+ int fd = -1;
+ if (std::find(console_names.begin(), console_names.end(), console_) != console_names.end()) {
+ std::string c_path = "/dev/" + console_;
+ fd = open(c_path.c_str(), O_RDWR);
}
+ if (fd == -1) fd = open("/dev/null", O_RDWR);
ioctl(fd, TIOCSCTTY, 0);
dup2(fd, 0);
dup2(fd, 1);
diff --git a/init/service.h b/init/service.h
index 35abde9b7..b003ca0cc 100644
--- a/init/service.h
+++ b/init/service.h
@@ -129,6 +129,7 @@ private:
std::string name_;
std::string classname_;
+ std::string console_;
unsigned flags_;
pid_t pid_;