blob: 5509b4f84dbd2285925a3e816cdb06e81aaff8f3 [file] [log] [blame]
// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "login_manager/systemd_unit_starter.h"
#include <string>
#include <vector>
#include <base/callback.h>
#include <base/logging.h>
#include <base/memory/scoped_ptr.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
namespace {
scoped_ptr<dbus::Response> CallEnvironmentMethod(
dbus::ObjectProxy *proxy,
const std::string &method_name,
const std::vector<std::string> &args_keyvals) {
DCHECK(proxy);
dbus::MethodCall method_call(login_manager::SystemdUnitStarter::kInterface,
method_name);
dbus::MessageWriter writer(&method_call);
writer.AppendArrayOfStrings(args_keyvals);
return proxy->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
}
scoped_ptr<dbus::Response> SetEnvironment(
dbus::ObjectProxy *proxy,
const std::vector<std::string> &args_keyvals) {
return CallEnvironmentMethod(
proxy,
login_manager::SystemdUnitStarter::kSetEnvironmentMethodName,
args_keyvals);
}
scoped_ptr<dbus::Response> UnsetEnvironment(
dbus::ObjectProxy *proxy,
const std::vector<std::string> &args_keyvals) {
std::vector<std::string> env_vars = args_keyvals;
std::string::size_type i = std::string::npos;
// Keep only the keys from environment array
for (std::vector<std::string>::iterator it=env_vars.begin();
it != env_vars.end();
++it ) {
i = it->find("=");
if (i != std::string::npos)
it->erase(i, it->length());
}
return CallEnvironmentMethod(
proxy,
login_manager::SystemdUnitStarter::kUnsetEnvironmentMethodName,
env_vars);
}
} // namespace
namespace login_manager {
const char SystemdUnitStarter::kServiceName[] = "org.freedesktop.systemd1";
const char SystemdUnitStarter::kPath[] = "/org/freedesktop/systemd1";
const char SystemdUnitStarter::kInterface[] =
"org.freedesktop.systemd1.Manager";
const char SystemdUnitStarter::kStartUnitMode[] = "replace";
const char SystemdUnitStarter::kStartUnitMethodName[] = "StartUnit";
const char SystemdUnitStarter::kSetEnvironmentMethodName[] = "SetEnvironment";
const char SystemdUnitStarter::kUnsetEnvironmentMethodName[] =
"UnsetEnvironment";
SystemdUnitStarter::SystemdUnitStarter(dbus::ObjectProxy *proxy)
: systemd_dbus_proxy_(proxy) {
}
SystemdUnitStarter::~SystemdUnitStarter() {
}
scoped_ptr<dbus::Response> SystemdUnitStarter::StartUnit(
const std::string &unit_name,
const std::vector<std::string> &args_keyvals ) {
DLOG(INFO) << "Starting " << unit_name << " unit";
scoped_ptr<dbus::Response> response;
// If we are not able to properly set the environment for the
// target unit, there is no point in going forward
if (!SetEnvironment(systemd_dbus_proxy_, args_keyvals)) {
DLOG(WARNING) << "Could not set environment for " << unit_name;
return nullptr;
}
dbus::MethodCall method_call(SystemdUnitStarter::kInterface,
SystemdUnitStarter::kStartUnitMethodName);
dbus::MessageWriter writer(&method_call);
writer.AppendString(unit_name + ".target");
writer.AppendString(SystemdUnitStarter::kStartUnitMode);
response = systemd_dbus_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
if (!UnsetEnvironment(systemd_dbus_proxy_, args_keyvals))
DLOG(WARNING) << "Unable to unset environment after starting" << unit_name;
return response;
}
scoped_ptr<dbus::Response> SystemdUnitStarter::TriggerImpulse(
const std::string &unit_name,
const std::vector<std::string> &args_keyvals) {
return StartUnit(unit_name, args_keyvals);
}
} // namespace login_manager