service.cpp revision af9ba4dc6ca98e136e887b0baa59b72fb8302dd3
1bac3299720623f4226bca103b26260052732ad30Tom Cherry/* 2bac3299720623f4226bca103b26260052732ad30Tom Cherry * Copyright (C) 2015 The Android Open Source Project 3bac3299720623f4226bca103b26260052732ad30Tom Cherry * 4bac3299720623f4226bca103b26260052732ad30Tom Cherry * Licensed under the Apache License, Version 2.0 (the "License"); 5bac3299720623f4226bca103b26260052732ad30Tom Cherry * you may not use this file except in compliance with the License. 6bac3299720623f4226bca103b26260052732ad30Tom Cherry * You may obtain a copy of the License at 7bac3299720623f4226bca103b26260052732ad30Tom Cherry * 8bac3299720623f4226bca103b26260052732ad30Tom Cherry * http://www.apache.org/licenses/LICENSE-2.0 9bac3299720623f4226bca103b26260052732ad30Tom Cherry * 10bac3299720623f4226bca103b26260052732ad30Tom Cherry * Unless required by applicable law or agreed to in writing, software 11bac3299720623f4226bca103b26260052732ad30Tom Cherry * distributed under the License is distributed on an "AS IS" BASIS, 12bac3299720623f4226bca103b26260052732ad30Tom Cherry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bac3299720623f4226bca103b26260052732ad30Tom Cherry * See the License for the specific language governing permissions and 14bac3299720623f4226bca103b26260052732ad30Tom Cherry * limitations under the License. 15bac3299720623f4226bca103b26260052732ad30Tom Cherry */ 16bac3299720623f4226bca103b26260052732ad30Tom Cherry 17bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "service.h" 18bac3299720623f4226bca103b26260052732ad30Tom Cherry 19bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <fcntl.h> 20bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <sys/stat.h> 21bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <sys/types.h> 22bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <termios.h> 23af9ba4dc6ca98e136e887b0baa59b72fb8302dd3Dan Albert#include <unistd.h> 24bac3299720623f4226bca103b26260052732ad30Tom Cherry 25bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <selinux/selinux.h> 26bac3299720623f4226bca103b26260052732ad30Tom Cherry 27bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <base/file.h> 28bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <base/stringprintf.h> 29bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <cutils/android_reboot.h> 30bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <cutils/sockets.h> 31bac3299720623f4226bca103b26260052732ad30Tom Cherry 32bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "action.h" 33bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "init.h" 34bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "init_parser.h" 35bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "keywords.h" 36bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "log.h" 37bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "property_service.h" 38bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "util.h" 39bac3299720623f4226bca103b26260052732ad30Tom Cherry 40bac3299720623f4226bca103b26260052732ad30Tom Cherry#define CRITICAL_CRASH_THRESHOLD 4 // if we crash >4 times ... 41bac3299720623f4226bca103b26260052732ad30Tom Cherry#define CRITICAL_CRASH_WINDOW (4*60) // ... in 4 minutes, goto recovery 42bac3299720623f4226bca103b26260052732ad30Tom Cherry 43bac3299720623f4226bca103b26260052732ad30Tom CherrySocketInfo::SocketInfo() : uid(0), gid(0), perm(0) { 44bac3299720623f4226bca103b26260052732ad30Tom Cherry} 45bac3299720623f4226bca103b26260052732ad30Tom Cherry 46bac3299720623f4226bca103b26260052732ad30Tom CherrySocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid, 47bac3299720623f4226bca103b26260052732ad30Tom Cherry gid_t gid, int perm, const std::string& socketcon) 48bac3299720623f4226bca103b26260052732ad30Tom Cherry : name(name), type(type), uid(uid), gid(gid), perm(perm), socketcon(socketcon) { 49bac3299720623f4226bca103b26260052732ad30Tom Cherry} 50bac3299720623f4226bca103b26260052732ad30Tom Cherry 51bac3299720623f4226bca103b26260052732ad30Tom CherryServiceEnvironmentInfo::ServiceEnvironmentInfo() { 52bac3299720623f4226bca103b26260052732ad30Tom Cherry} 53bac3299720623f4226bca103b26260052732ad30Tom Cherry 54bac3299720623f4226bca103b26260052732ad30Tom CherryServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name, 55bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::string& value) 56bac3299720623f4226bca103b26260052732ad30Tom Cherry : name(name), value(value) { 57bac3299720623f4226bca103b26260052732ad30Tom Cherry} 58bac3299720623f4226bca103b26260052732ad30Tom Cherry 59bac3299720623f4226bca103b26260052732ad30Tom CherryService::Service(const std::string& name, const std::string& classname, 60bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::vector<std::string>& args) 61bac3299720623f4226bca103b26260052732ad30Tom Cherry : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0), 62bac3299720623f4226bca103b26260052732ad30Tom Cherry time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), seclabel_(""), 63bac3299720623f4226bca103b26260052732ad30Tom Cherry ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), args_(args) { 64bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.InitSingleTrigger("onrestart"); 65bac3299720623f4226bca103b26260052732ad30Tom Cherry} 66bac3299720623f4226bca103b26260052732ad30Tom Cherry 67bac3299720623f4226bca103b26260052732ad30Tom CherryService::Service(const std::string& name, const std::string& classname, 68bac3299720623f4226bca103b26260052732ad30Tom Cherry unsigned flags, uid_t uid, gid_t gid, const std::vector<gid_t>& supp_gids, 69bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::string& seclabel, const std::vector<std::string>& args) 70bac3299720623f4226bca103b26260052732ad30Tom Cherry : name_(name), classname_(classname), flags_(flags), pid_(0), time_started_(0), 71bac3299720623f4226bca103b26260052732ad30Tom Cherry time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid), supp_gids_(supp_gids), 72bac3299720623f4226bca103b26260052732ad30Tom Cherry seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), args_(args) { 73bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.InitSingleTrigger("onrestart"); 74bac3299720623f4226bca103b26260052732ad30Tom Cherry} 75bac3299720623f4226bca103b26260052732ad30Tom Cherry 76bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::NotifyStateChange(const std::string& new_state) const { 77bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!properties_initialized()) { 78bac3299720623f4226bca103b26260052732ad30Tom Cherry // If properties aren't available yet, we can't set them. 79bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 80bac3299720623f4226bca103b26260052732ad30Tom Cherry } 81bac3299720623f4226bca103b26260052732ad30Tom Cherry 82bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_EXEC) != 0) { 83bac3299720623f4226bca103b26260052732ad30Tom Cherry // 'exec' commands don't have properties tracking their state. 84bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 85bac3299720623f4226bca103b26260052732ad30Tom Cherry } 86bac3299720623f4226bca103b26260052732ad30Tom Cherry 87bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string prop_name = android::base::StringPrintf("init.svc.%s", name_.c_str()); 88bac3299720623f4226bca103b26260052732ad30Tom Cherry if (prop_name.length() >= PROP_NAME_MAX) { 89bac3299720623f4226bca103b26260052732ad30Tom Cherry // If the property name would be too long, we can't set it. 90bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Property name \"init.svc.%s\" too long; not setting to %s\n", 91bac3299720623f4226bca103b26260052732ad30Tom Cherry name_.c_str(), new_state.c_str()); 92bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 93bac3299720623f4226bca103b26260052732ad30Tom Cherry } 94bac3299720623f4226bca103b26260052732ad30Tom Cherry 95bac3299720623f4226bca103b26260052732ad30Tom Cherry property_set(prop_name.c_str(), new_state.c_str()); 96bac3299720623f4226bca103b26260052732ad30Tom Cherry} 97bac3299720623f4226bca103b26260052732ad30Tom Cherry 98bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Reap() { 99bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) { 100bac3299720623f4226bca103b26260052732ad30Tom Cherry NOTICE("Service '%s' (pid %d) killing any children in process group\n", 101bac3299720623f4226bca103b26260052732ad30Tom Cherry name_.c_str(), pid_); 102bac3299720623f4226bca103b26260052732ad30Tom Cherry kill(-pid_, SIGKILL); 103bac3299720623f4226bca103b26260052732ad30Tom Cherry } 104bac3299720623f4226bca103b26260052732ad30Tom Cherry 105bac3299720623f4226bca103b26260052732ad30Tom Cherry // Remove any sockets we may have created. 106bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 107bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string tmp = android::base::StringPrintf(ANDROID_SOCKET_DIR "/%s", 108bac3299720623f4226bca103b26260052732ad30Tom Cherry si.name.c_str()); 109bac3299720623f4226bca103b26260052732ad30Tom Cherry unlink(tmp.c_str()); 110bac3299720623f4226bca103b26260052732ad30Tom Cherry } 111bac3299720623f4226bca103b26260052732ad30Tom Cherry 112bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_EXEC) { 113bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("SVC_EXEC pid %d finished...\n", pid_); 114bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 115bac3299720623f4226bca103b26260052732ad30Tom Cherry } 116bac3299720623f4226bca103b26260052732ad30Tom Cherry 117bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = 0; 118bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RUNNING); 119bac3299720623f4226bca103b26260052732ad30Tom Cherry 120bac3299720623f4226bca103b26260052732ad30Tom Cherry // Oneshot processes go into the disabled state on exit, 121bac3299720623f4226bca103b26260052732ad30Tom Cherry // except when manually restarted. 122bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) { 123bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 124bac3299720623f4226bca103b26260052732ad30Tom Cherry } 125bac3299720623f4226bca103b26260052732ad30Tom Cherry 126bac3299720623f4226bca103b26260052732ad30Tom Cherry // Disabled and reset processes do not get restarted automatically. 127bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & (SVC_DISABLED | SVC_RESET)) { 128bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopped"); 129bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 130bac3299720623f4226bca103b26260052732ad30Tom Cherry } 131bac3299720623f4226bca103b26260052732ad30Tom Cherry 132bac3299720623f4226bca103b26260052732ad30Tom Cherry time_t now = gettime(); 133bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) { 134bac3299720623f4226bca103b26260052732ad30Tom Cherry if (time_crashed_ + CRITICAL_CRASH_WINDOW >= now) { 135bac3299720623f4226bca103b26260052732ad30Tom Cherry if (++nr_crashed_ > CRITICAL_CRASH_THRESHOLD) { 136bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("critical process '%s' exited %d times in %d minutes; " 137bac3299720623f4226bca103b26260052732ad30Tom Cherry "rebooting into recovery mode\n", name_.c_str(), 138bac3299720623f4226bca103b26260052732ad30Tom Cherry CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60); 139bac3299720623f4226bca103b26260052732ad30Tom Cherry android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); 140bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 141bac3299720623f4226bca103b26260052732ad30Tom Cherry } 142bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 143bac3299720623f4226bca103b26260052732ad30Tom Cherry time_crashed_ = now; 144bac3299720623f4226bca103b26260052732ad30Tom Cherry nr_crashed_ = 1; 145bac3299720623f4226bca103b26260052732ad30Tom Cherry } 146bac3299720623f4226bca103b26260052732ad30Tom Cherry } 147bac3299720623f4226bca103b26260052732ad30Tom Cherry 148bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RESTART); 149bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_RESTARTING; 150bac3299720623f4226bca103b26260052732ad30Tom Cherry 151bac3299720623f4226bca103b26260052732ad30Tom Cherry // Execute all onrestart commands for this service. 152bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.ExecuteAllCommands(); 153bac3299720623f4226bca103b26260052732ad30Tom Cherry 154bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("restarting"); 155bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 156bac3299720623f4226bca103b26260052732ad30Tom Cherry} 157bac3299720623f4226bca103b26260052732ad30Tom Cherry 158bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::DumpState() const { 159bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("service %s\n", name_.c_str()); 160bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO(" class '%s'\n", classname_.c_str()); 161bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO(" exec"); 162bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : args_) { 163bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO(" '%s'", s.c_str()); 164bac3299720623f4226bca103b26260052732ad30Tom Cherry } 165bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("\n"); 166bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 167bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO(" socket %s %s 0%o\n", si.name.c_str(), si.type.c_str(), si.perm); 168bac3299720623f4226bca103b26260052732ad30Tom Cherry } 169bac3299720623f4226bca103b26260052732ad30Tom Cherry} 170bac3299720623f4226bca103b26260052732ad30Tom Cherry 171bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::HandleLine(int kw, const std::vector<std::string>& args, std::string* err) { 172bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<std::string> str_args; 173bac3299720623f4226bca103b26260052732ad30Tom Cherry 174bac3299720623f4226bca103b26260052732ad30Tom Cherry ioprio_class_ = IoSchedClass_NONE; 175bac3299720623f4226bca103b26260052732ad30Tom Cherry 176bac3299720623f4226bca103b26260052732ad30Tom Cherry switch (kw) { 177bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_class: 178bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() != 2) { 179bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "class option requires a classname\n"; 180bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 181bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 182bac3299720623f4226bca103b26260052732ad30Tom Cherry classname_ = args[1]; 183bac3299720623f4226bca103b26260052732ad30Tom Cherry } 184bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 185bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_console: 186bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_CONSOLE; 187bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 188bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_disabled: 189bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 190bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_RC_DISABLED; 191bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 192bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_ioprio: 193bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() != 3) { 194bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "ioprio optin usage: ioprio <rt|be|idle> <ioprio 0-7>\n"; 195bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 196bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 197bac3299720623f4226bca103b26260052732ad30Tom Cherry ioprio_pri_ = std::stoul(args[2], 0, 8); 198bac3299720623f4226bca103b26260052732ad30Tom Cherry 199bac3299720623f4226bca103b26260052732ad30Tom Cherry if (ioprio_pri_ < 0 || ioprio_pri_ > 7) { 200bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "priority value must be range 0 - 7\n"; 201bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 202bac3299720623f4226bca103b26260052732ad30Tom Cherry } 203bac3299720623f4226bca103b26260052732ad30Tom Cherry 204bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args[1] == "rt") { 205bac3299720623f4226bca103b26260052732ad30Tom Cherry ioprio_class_ = IoSchedClass_RT; 206bac3299720623f4226bca103b26260052732ad30Tom Cherry } else if (args[1] == "be") { 207bac3299720623f4226bca103b26260052732ad30Tom Cherry ioprio_class_ = IoSchedClass_BE; 208bac3299720623f4226bca103b26260052732ad30Tom Cherry } else if (args[1] == "idle") { 209bac3299720623f4226bca103b26260052732ad30Tom Cherry ioprio_class_ = IoSchedClass_IDLE; 210bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 211bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "ioprio option usage: ioprio <rt|be|idle> <0-7>\n"; 212bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 213bac3299720623f4226bca103b26260052732ad30Tom Cherry } 214bac3299720623f4226bca103b26260052732ad30Tom Cherry } 215bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 216bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_group: 217bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() < 2) { 218bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "group option requires a group id\n"; 219bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 220bac3299720623f4226bca103b26260052732ad30Tom Cherry } else if (args.size() > NR_SVC_SUPP_GIDS + 2) { 221bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = android::base::StringPrintf("group option accepts at most %d supp. groups\n", 222bac3299720623f4226bca103b26260052732ad30Tom Cherry NR_SVC_SUPP_GIDS); 223bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 224bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 225bac3299720623f4226bca103b26260052732ad30Tom Cherry gid_ = decode_uid(args[1].c_str()); 226bac3299720623f4226bca103b26260052732ad30Tom Cherry for (std::size_t n = 2; n < args.size(); n++) { 227bac3299720623f4226bca103b26260052732ad30Tom Cherry supp_gids_.push_back(decode_uid(args[n].c_str())); 228bac3299720623f4226bca103b26260052732ad30Tom Cherry } 229bac3299720623f4226bca103b26260052732ad30Tom Cherry } 230bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 231bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_keycodes: 232bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() < 2) { 233bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "keycodes option requires atleast one keycode\n"; 234bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 235bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 236bac3299720623f4226bca103b26260052732ad30Tom Cherry for (std::size_t i = 1; i < args.size(); i++) { 237bac3299720623f4226bca103b26260052732ad30Tom Cherry keycodes_.push_back(std::stoi(args[i])); 238bac3299720623f4226bca103b26260052732ad30Tom Cherry } 239bac3299720623f4226bca103b26260052732ad30Tom Cherry } 240bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 241bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_oneshot: 242bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_ONESHOT; 243bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 244bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_onrestart: 245bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() < 2) { 246bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 247bac3299720623f4226bca103b26260052732ad30Tom Cherry } 248bac3299720623f4226bca103b26260052732ad30Tom Cherry str_args.assign(args.begin() + 1, args.end()); 249bac3299720623f4226bca103b26260052732ad30Tom Cherry add_command_to_action(&onrestart_, str_args, "", 0, err); 250bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 251bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_critical: 252bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_CRITICAL; 253bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 254bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_setenv: { /* name value */ 255bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() < 3) { 256bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "setenv option requires name and value arguments\n"; 257bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 258bac3299720623f4226bca103b26260052732ad30Tom Cherry } 259bac3299720623f4226bca103b26260052732ad30Tom Cherry 260bac3299720623f4226bca103b26260052732ad30Tom Cherry envvars_.push_back({args[1], args[2]}); 261bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 262bac3299720623f4226bca103b26260052732ad30Tom Cherry } 263bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_socket: {/* name type perm [ uid gid context ] */ 264bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() < 4) { 265bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "socket option requires name, type, perm arguments\n"; 266bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 267bac3299720623f4226bca103b26260052732ad30Tom Cherry } 268bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args[2] != "dgram" && args[2] != "stream" && 269bac3299720623f4226bca103b26260052732ad30Tom Cherry args[2] != "seqpacket") { 270bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "socket type must be 'dgram', 'stream' or 'seqpacket'\n"; 271bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 272bac3299720623f4226bca103b26260052732ad30Tom Cherry } 273bac3299720623f4226bca103b26260052732ad30Tom Cherry 274bac3299720623f4226bca103b26260052732ad30Tom Cherry int perm = std::stoul(args[3], 0, 8); 275bac3299720623f4226bca103b26260052732ad30Tom Cherry uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0; 276bac3299720623f4226bca103b26260052732ad30Tom Cherry gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0; 277bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string socketcon = args.size() > 6 ? args[6] : ""; 278bac3299720623f4226bca103b26260052732ad30Tom Cherry 279bac3299720623f4226bca103b26260052732ad30Tom Cherry sockets_.push_back({args[1], args[2], uid, gid, perm, socketcon}); 280bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 281bac3299720623f4226bca103b26260052732ad30Tom Cherry } 282bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_user: 283bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() != 2) { 284bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "user option requires a user id\n"; 285bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 286bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 287bac3299720623f4226bca103b26260052732ad30Tom Cherry uid_ = decode_uid(args[1].c_str()); 288bac3299720623f4226bca103b26260052732ad30Tom Cherry } 289bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 290bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_seclabel: 291bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() != 2) { 292bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "seclabel option requires a label string\n"; 293bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 294bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 295bac3299720623f4226bca103b26260052732ad30Tom Cherry seclabel_ = args[1]; 296bac3299720623f4226bca103b26260052732ad30Tom Cherry } 297bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 298bac3299720623f4226bca103b26260052732ad30Tom Cherry case K_writepid: 299bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args.size() < 2) { 300bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = "writepid option requires at least one filename\n"; 301bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 302bac3299720623f4226bca103b26260052732ad30Tom Cherry } 303bac3299720623f4226bca103b26260052732ad30Tom Cherry writepid_files_.assign(args.begin() + 1, args.end()); 304bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 305bac3299720623f4226bca103b26260052732ad30Tom Cherry 306bac3299720623f4226bca103b26260052732ad30Tom Cherry default: 307bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = android::base::StringPrintf("invalid option '%s'\n", args[0].c_str()); 308bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 309bac3299720623f4226bca103b26260052732ad30Tom Cherry } 310bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 311bac3299720623f4226bca103b26260052732ad30Tom Cherry} 312bac3299720623f4226bca103b26260052732ad30Tom Cherry 313bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Start(const std::vector<std::string>& dynamic_args) { 314bac3299720623f4226bca103b26260052732ad30Tom Cherry // Starting a service removes it from the disabled or reset state and 315bac3299720623f4226bca103b26260052732ad30Tom Cherry // immediately takes it out of the restarting state if it was in there. 316bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START)); 317bac3299720623f4226bca103b26260052732ad30Tom Cherry time_started_ = 0; 318bac3299720623f4226bca103b26260052732ad30Tom Cherry 319bac3299720623f4226bca103b26260052732ad30Tom Cherry // Running processes require no additional work --- if they're in the 320bac3299720623f4226bca103b26260052732ad30Tom Cherry // process of exiting, we've ensured that they will immediately restart 321bac3299720623f4226bca103b26260052732ad30Tom Cherry // on exit, unless they are ONESHOT. 322bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_RUNNING) { 323bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 324bac3299720623f4226bca103b26260052732ad30Tom Cherry } 325bac3299720623f4226bca103b26260052732ad30Tom Cherry 326bac3299720623f4226bca103b26260052732ad30Tom Cherry bool needs_console = (flags_ & SVC_CONSOLE); 327bac3299720623f4226bca103b26260052732ad30Tom Cherry if (needs_console && !have_console) { 328bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("service '%s' requires console\n", name_.c_str()); 329bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 330bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 331bac3299720623f4226bca103b26260052732ad30Tom Cherry } 332bac3299720623f4226bca103b26260052732ad30Tom Cherry 333bac3299720623f4226bca103b26260052732ad30Tom Cherry struct stat sb; 334bac3299720623f4226bca103b26260052732ad30Tom Cherry if (stat(args_[0].c_str(), &sb) == -1) { 335bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("cannot find '%s' (%s), disabling '%s'\n", 336bac3299720623f4226bca103b26260052732ad30Tom Cherry args_[0].c_str(), strerror(errno), name_.c_str()); 337bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 338bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 339bac3299720623f4226bca103b26260052732ad30Tom Cherry } 340bac3299720623f4226bca103b26260052732ad30Tom Cherry 341bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((!(flags_ & SVC_ONESHOT)) && !dynamic_args.empty()) { 342bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", 343bac3299720623f4226bca103b26260052732ad30Tom Cherry args_[0].c_str()); 344bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 345bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 346bac3299720623f4226bca103b26260052732ad30Tom Cherry } 347bac3299720623f4226bca103b26260052732ad30Tom Cherry 348bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string scon; 349bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!seclabel_.empty()) { 350bac3299720623f4226bca103b26260052732ad30Tom Cherry scon = seclabel_; 351bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 352bac3299720623f4226bca103b26260052732ad30Tom Cherry char* mycon = nullptr; 353bac3299720623f4226bca103b26260052732ad30Tom Cherry char* fcon = nullptr; 354bac3299720623f4226bca103b26260052732ad30Tom Cherry 355bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("computing context for service '%s'\n", args_[0].c_str()); 356bac3299720623f4226bca103b26260052732ad30Tom Cherry int rc = getcon(&mycon); 357bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 358bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("could not get context while starting '%s'\n", name_.c_str()); 359bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 360bac3299720623f4226bca103b26260052732ad30Tom Cherry } 361bac3299720623f4226bca103b26260052732ad30Tom Cherry 362bac3299720623f4226bca103b26260052732ad30Tom Cherry rc = getfilecon(args_[0].c_str(), &fcon); 363bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 364bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("could not get context while starting '%s'\n", name_.c_str()); 365bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 366bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 367bac3299720623f4226bca103b26260052732ad30Tom Cherry } 368bac3299720623f4226bca103b26260052732ad30Tom Cherry 369bac3299720623f4226bca103b26260052732ad30Tom Cherry char* ret_scon = nullptr; 370bac3299720623f4226bca103b26260052732ad30Tom Cherry rc = security_compute_create(mycon, fcon, string_to_security_class("process"), 371bac3299720623f4226bca103b26260052732ad30Tom Cherry &ret_scon); 372bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc == 0) { 373bac3299720623f4226bca103b26260052732ad30Tom Cherry scon = ret_scon; 374bac3299720623f4226bca103b26260052732ad30Tom Cherry free(ret_scon); 375bac3299720623f4226bca103b26260052732ad30Tom Cherry } 376bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc == 0 && scon == mycon) { 377bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Service %s does not have a SELinux domain defined.\n", name_.c_str()); 378bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 379bac3299720623f4226bca103b26260052732ad30Tom Cherry free(fcon); 380bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 381bac3299720623f4226bca103b26260052732ad30Tom Cherry } 382bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 383bac3299720623f4226bca103b26260052732ad30Tom Cherry free(fcon); 384bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 385bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("could not get context while starting '%s'\n", name_.c_str()); 386bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 387bac3299720623f4226bca103b26260052732ad30Tom Cherry } 388bac3299720623f4226bca103b26260052732ad30Tom Cherry } 389bac3299720623f4226bca103b26260052732ad30Tom Cherry 390bac3299720623f4226bca103b26260052732ad30Tom Cherry NOTICE("Starting service '%s'...\n", name_.c_str()); 391bac3299720623f4226bca103b26260052732ad30Tom Cherry 392bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_t pid = fork(); 393bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid == 0) { 394bac3299720623f4226bca103b26260052732ad30Tom Cherry int fd, sz; 395bac3299720623f4226bca103b26260052732ad30Tom Cherry 396bac3299720623f4226bca103b26260052732ad30Tom Cherry umask(077); 397bac3299720623f4226bca103b26260052732ad30Tom Cherry if (properties_initialized()) { 398bac3299720623f4226bca103b26260052732ad30Tom Cherry get_property_workspace(&fd, &sz); 399bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string tmp = android::base::StringPrintf("%d,%d", dup(fd), sz); 400bac3299720623f4226bca103b26260052732ad30Tom Cherry add_environment("ANDROID_PROPERTY_WORKSPACE", tmp.c_str()); 401bac3299720623f4226bca103b26260052732ad30Tom Cherry } 402bac3299720623f4226bca103b26260052732ad30Tom Cherry 403bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& ei : envvars_) { 404bac3299720623f4226bca103b26260052732ad30Tom Cherry add_environment(ei.name.c_str(), ei.value.c_str()); 405bac3299720623f4226bca103b26260052732ad30Tom Cherry } 406bac3299720623f4226bca103b26260052732ad30Tom Cherry 407bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 408bac3299720623f4226bca103b26260052732ad30Tom Cherry int socket_type = ((si.type == "stream" ? SOCK_STREAM : 409bac3299720623f4226bca103b26260052732ad30Tom Cherry (si.type == "dgram" ? SOCK_DGRAM : 410bac3299720623f4226bca103b26260052732ad30Tom Cherry SOCK_SEQPACKET))); 411bac3299720623f4226bca103b26260052732ad30Tom Cherry const char* socketcon = 412bac3299720623f4226bca103b26260052732ad30Tom Cherry !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str(); 413bac3299720623f4226bca103b26260052732ad30Tom Cherry 414bac3299720623f4226bca103b26260052732ad30Tom Cherry int s = create_socket(si.name.c_str(), socket_type, si.perm, 415bac3299720623f4226bca103b26260052732ad30Tom Cherry si.uid, si.gid, socketcon); 416bac3299720623f4226bca103b26260052732ad30Tom Cherry if (s >= 0) { 417bac3299720623f4226bca103b26260052732ad30Tom Cherry PublishSocket(si.name, s); 418bac3299720623f4226bca103b26260052732ad30Tom Cherry } 419bac3299720623f4226bca103b26260052732ad30Tom Cherry } 420bac3299720623f4226bca103b26260052732ad30Tom Cherry 421bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string pid_str = android::base::StringPrintf("%d", pid); 422bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& file : writepid_files_) { 423bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!android::base::WriteStringToFile(pid_str, file)) { 424bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("couldn't write %s to %s: %s\n", 425bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_str.c_str(), file.c_str(), strerror(errno)); 426bac3299720623f4226bca103b26260052732ad30Tom Cherry } 427bac3299720623f4226bca103b26260052732ad30Tom Cherry } 428bac3299720623f4226bca103b26260052732ad30Tom Cherry 429bac3299720623f4226bca103b26260052732ad30Tom Cherry if (ioprio_class_ != IoSchedClass_NONE) { 430bac3299720623f4226bca103b26260052732ad30Tom Cherry if (android_set_ioprio(getpid(), ioprio_class_, ioprio_pri_)) { 431bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Failed to set pid %d ioprio = %d,%d: %s\n", 432bac3299720623f4226bca103b26260052732ad30Tom Cherry getpid(), ioprio_class_, ioprio_pri_, strerror(errno)); 433bac3299720623f4226bca103b26260052732ad30Tom Cherry } 434bac3299720623f4226bca103b26260052732ad30Tom Cherry } 435bac3299720623f4226bca103b26260052732ad30Tom Cherry 436bac3299720623f4226bca103b26260052732ad30Tom Cherry if (needs_console) { 437bac3299720623f4226bca103b26260052732ad30Tom Cherry setsid(); 438bac3299720623f4226bca103b26260052732ad30Tom Cherry OpenConsole(); 439bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 440bac3299720623f4226bca103b26260052732ad30Tom Cherry ZapStdio(); 441bac3299720623f4226bca103b26260052732ad30Tom Cherry } 442bac3299720623f4226bca103b26260052732ad30Tom Cherry 443bac3299720623f4226bca103b26260052732ad30Tom Cherry setpgid(0, getpid()); 444bac3299720623f4226bca103b26260052732ad30Tom Cherry 445bac3299720623f4226bca103b26260052732ad30Tom Cherry // As requested, set our gid, supplemental gids, and uid. 446bac3299720623f4226bca103b26260052732ad30Tom Cherry if (gid_) { 447bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setgid(gid_) != 0) { 448bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("setgid failed: %s\n", strerror(errno)); 449bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 450bac3299720623f4226bca103b26260052732ad30Tom Cherry } 451bac3299720623f4226bca103b26260052732ad30Tom Cherry } 452bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!supp_gids_.empty()) { 453bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setgroups(supp_gids_.size(), &supp_gids_[0]) != 0) { 454bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("setgroups failed: %s\n", strerror(errno)); 455bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 456bac3299720623f4226bca103b26260052732ad30Tom Cherry } 457bac3299720623f4226bca103b26260052732ad30Tom Cherry } 458bac3299720623f4226bca103b26260052732ad30Tom Cherry if (uid_) { 459bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setuid(uid_) != 0) { 460bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("setuid failed: %s\n", strerror(errno)); 461bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 462bac3299720623f4226bca103b26260052732ad30Tom Cherry } 463bac3299720623f4226bca103b26260052732ad30Tom Cherry } 464bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!seclabel_.empty()) { 465bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setexeccon(seclabel_.c_str()) < 0) { 466bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("cannot setexeccon('%s'): %s\n", 467bac3299720623f4226bca103b26260052732ad30Tom Cherry seclabel_.c_str(), strerror(errno)); 468bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 469bac3299720623f4226bca103b26260052732ad30Tom Cherry } 470bac3299720623f4226bca103b26260052732ad30Tom Cherry } 471bac3299720623f4226bca103b26260052732ad30Tom Cherry 472bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<char*> strs; 473bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : args_) { 474bac3299720623f4226bca103b26260052732ad30Tom Cherry strs.push_back(const_cast<char*>(s.c_str())); 475bac3299720623f4226bca103b26260052732ad30Tom Cherry } 476bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : dynamic_args) { 477bac3299720623f4226bca103b26260052732ad30Tom Cherry strs.push_back(const_cast<char*>(s.c_str())); 478bac3299720623f4226bca103b26260052732ad30Tom Cherry } 479bac3299720623f4226bca103b26260052732ad30Tom Cherry strs.push_back(nullptr); 480bac3299720623f4226bca103b26260052732ad30Tom Cherry if (execve(args_[0].c_str(), (char**) &strs[0], (char**) ENV) < 0) { 481bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("cannot execve('%s'): %s\n", args_[0].c_str(), strerror(errno)); 482bac3299720623f4226bca103b26260052732ad30Tom Cherry } 483bac3299720623f4226bca103b26260052732ad30Tom Cherry 484bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 485bac3299720623f4226bca103b26260052732ad30Tom Cherry } 486bac3299720623f4226bca103b26260052732ad30Tom Cherry 487bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid < 0) { 488bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("failed to start '%s'\n", name_.c_str()); 489bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = 0; 490bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 491bac3299720623f4226bca103b26260052732ad30Tom Cherry } 492bac3299720623f4226bca103b26260052732ad30Tom Cherry 493bac3299720623f4226bca103b26260052732ad30Tom Cherry time_started_ = gettime(); 494bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = pid; 495bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_RUNNING; 496bac3299720623f4226bca103b26260052732ad30Tom Cherry 497bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_EXEC) != 0) { 498bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n", 499bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_, uid_, gid_, supp_gids_.size(), 500bac3299720623f4226bca103b26260052732ad30Tom Cherry !seclabel_.empty() ? seclabel_.c_str() : "default"); 501bac3299720623f4226bca103b26260052732ad30Tom Cherry } 502bac3299720623f4226bca103b26260052732ad30Tom Cherry 503bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("running"); 504bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 505bac3299720623f4226bca103b26260052732ad30Tom Cherry} 506bac3299720623f4226bca103b26260052732ad30Tom Cherry 507bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Start() { 508bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::vector<std::string> null_dynamic_args; 509bac3299720623f4226bca103b26260052732ad30Tom Cherry return Start(null_dynamic_args); 510bac3299720623f4226bca103b26260052732ad30Tom Cherry} 511bac3299720623f4226bca103b26260052732ad30Tom Cherry 512bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::StartIfNotDisabled() { 513bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!(flags_ & SVC_DISABLED)) { 514bac3299720623f4226bca103b26260052732ad30Tom Cherry return Start(); 515bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 516bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED_START; 517bac3299720623f4226bca103b26260052732ad30Tom Cherry } 518bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 519bac3299720623f4226bca103b26260052732ad30Tom Cherry} 520bac3299720623f4226bca103b26260052732ad30Tom Cherry 521bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Enable() { 522bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED); 523bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_DISABLED_START) { 524bac3299720623f4226bca103b26260052732ad30Tom Cherry return Start(); 525bac3299720623f4226bca103b26260052732ad30Tom Cherry } 526bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 527bac3299720623f4226bca103b26260052732ad30Tom Cherry} 528bac3299720623f4226bca103b26260052732ad30Tom Cherry 529bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Reset() { 530bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_RESET); 531bac3299720623f4226bca103b26260052732ad30Tom Cherry} 532bac3299720623f4226bca103b26260052732ad30Tom Cherry 533bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Stop() { 534bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_DISABLED); 535bac3299720623f4226bca103b26260052732ad30Tom Cherry} 536bac3299720623f4226bca103b26260052732ad30Tom Cherry 537bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Restart() { 538bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_RUNNING) { 539bac3299720623f4226bca103b26260052732ad30Tom Cherry /* Stop, wait, then start the service. */ 540bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_RESTART); 541bac3299720623f4226bca103b26260052732ad30Tom Cherry } else if (!(flags_ & SVC_RESTARTING)) { 542bac3299720623f4226bca103b26260052732ad30Tom Cherry /* Just start the service since it's not running. */ 543bac3299720623f4226bca103b26260052732ad30Tom Cherry Start(); 544bac3299720623f4226bca103b26260052732ad30Tom Cherry } /* else: Service is restarting anyways. */ 545bac3299720623f4226bca103b26260052732ad30Tom Cherry} 546bac3299720623f4226bca103b26260052732ad30Tom Cherry 547bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::RestartIfNeeded(time_t& process_needs_restart) { 548bac3299720623f4226bca103b26260052732ad30Tom Cherry time_t next_start_time = time_started_ + 5; 549bac3299720623f4226bca103b26260052732ad30Tom Cherry 550bac3299720623f4226bca103b26260052732ad30Tom Cherry if (next_start_time <= gettime()) { 551bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RESTARTING); 552bac3299720623f4226bca103b26260052732ad30Tom Cherry Start(); 553bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 554bac3299720623f4226bca103b26260052732ad30Tom Cherry } 555bac3299720623f4226bca103b26260052732ad30Tom Cherry 556bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((next_start_time < process_needs_restart) || 557bac3299720623f4226bca103b26260052732ad30Tom Cherry (process_needs_restart == 0)) { 558bac3299720623f4226bca103b26260052732ad30Tom Cherry process_needs_restart = next_start_time; 559bac3299720623f4226bca103b26260052732ad30Tom Cherry } 560bac3299720623f4226bca103b26260052732ad30Tom Cherry} 561bac3299720623f4226bca103b26260052732ad30Tom Cherry 562bac3299720623f4226bca103b26260052732ad30Tom Cherry/* The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART */ 563bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::StopOrReset(int how) { 564bac3299720623f4226bca103b26260052732ad30Tom Cherry /* The service is still SVC_RUNNING until its process exits, but if it has 565bac3299720623f4226bca103b26260052732ad30Tom Cherry * already exited it shoudn't attempt a restart yet. */ 566bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START); 567bac3299720623f4226bca103b26260052732ad30Tom Cherry 568bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) { 569bac3299720623f4226bca103b26260052732ad30Tom Cherry /* Hrm, an illegal flag. Default to SVC_DISABLED */ 570bac3299720623f4226bca103b26260052732ad30Tom Cherry how = SVC_DISABLED; 571bac3299720623f4226bca103b26260052732ad30Tom Cherry } 572bac3299720623f4226bca103b26260052732ad30Tom Cherry /* if the service has not yet started, prevent 573bac3299720623f4226bca103b26260052732ad30Tom Cherry * it from auto-starting with its class 574bac3299720623f4226bca103b26260052732ad30Tom Cherry */ 575bac3299720623f4226bca103b26260052732ad30Tom Cherry if (how == SVC_RESET) { 576bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= (flags_ & SVC_RC_DISABLED) ? SVC_DISABLED : SVC_RESET; 577bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 578bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= how; 579bac3299720623f4226bca103b26260052732ad30Tom Cherry } 580bac3299720623f4226bca103b26260052732ad30Tom Cherry 581bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid_) { 582bac3299720623f4226bca103b26260052732ad30Tom Cherry NOTICE("Service '%s' is being killed...\n", name_.c_str()); 583bac3299720623f4226bca103b26260052732ad30Tom Cherry kill(-pid_, SIGKILL); 584bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopping"); 585bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 586bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopped"); 587bac3299720623f4226bca103b26260052732ad30Tom Cherry } 588bac3299720623f4226bca103b26260052732ad30Tom Cherry} 589bac3299720623f4226bca103b26260052732ad30Tom Cherry 590bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::ZapStdio() const { 591bac3299720623f4226bca103b26260052732ad30Tom Cherry int fd; 592bac3299720623f4226bca103b26260052732ad30Tom Cherry fd = open("/dev/null", O_RDWR); 593bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 0); 594bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 1); 595bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 2); 596bac3299720623f4226bca103b26260052732ad30Tom Cherry close(fd); 597bac3299720623f4226bca103b26260052732ad30Tom Cherry} 598bac3299720623f4226bca103b26260052732ad30Tom Cherry 599bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::OpenConsole() const { 600bac3299720623f4226bca103b26260052732ad30Tom Cherry int fd; 601bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((fd = open(console_name.c_str(), O_RDWR)) < 0) { 602bac3299720623f4226bca103b26260052732ad30Tom Cherry fd = open("/dev/null", O_RDWR); 603bac3299720623f4226bca103b26260052732ad30Tom Cherry } 604bac3299720623f4226bca103b26260052732ad30Tom Cherry ioctl(fd, TIOCSCTTY, 0); 605bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 0); 606bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 1); 607bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 2); 608bac3299720623f4226bca103b26260052732ad30Tom Cherry close(fd); 609bac3299720623f4226bca103b26260052732ad30Tom Cherry} 610bac3299720623f4226bca103b26260052732ad30Tom Cherry 611bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::PublishSocket(const std::string& name, int fd) const { 612bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string key = android::base::StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", 613bac3299720623f4226bca103b26260052732ad30Tom Cherry name.c_str()); 614bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string val = android::base::StringPrintf("%d", fd); 615bac3299720623f4226bca103b26260052732ad30Tom Cherry add_environment(key.c_str(), val.c_str()); 616bac3299720623f4226bca103b26260052732ad30Tom Cherry 617bac3299720623f4226bca103b26260052732ad30Tom Cherry /* make sure we don't close-on-exec */ 618bac3299720623f4226bca103b26260052732ad30Tom Cherry fcntl(fd, F_SETFD, 0); 619bac3299720623f4226bca103b26260052732ad30Tom Cherry} 620bac3299720623f4226bca103b26260052732ad30Tom Cherry 621bac3299720623f4226bca103b26260052732ad30Tom Cherryint ServiceManager::exec_count_ = 0; 622bac3299720623f4226bca103b26260052732ad30Tom Cherry 623bac3299720623f4226bca103b26260052732ad30Tom CherryServiceManager::ServiceManager() { 624bac3299720623f4226bca103b26260052732ad30Tom Cherry} 625bac3299720623f4226bca103b26260052732ad30Tom Cherry 626bac3299720623f4226bca103b26260052732ad30Tom CherryServiceManager& ServiceManager::GetInstance() { 627bac3299720623f4226bca103b26260052732ad30Tom Cherry static ServiceManager instance; 628bac3299720623f4226bca103b26260052732ad30Tom Cherry return instance; 629bac3299720623f4226bca103b26260052732ad30Tom Cherry} 630bac3299720623f4226bca103b26260052732ad30Tom Cherry 631bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::AddNewService(const std::string& name, 632bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::string& classname, 633bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::vector<std::string>& args, 634bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string* err) { 635bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!IsValidName(name)) { 636bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = android::base::StringPrintf("invalid service name '%s'\n", name.c_str()); 637bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 638bac3299720623f4226bca103b26260052732ad30Tom Cherry } 639bac3299720623f4226bca103b26260052732ad30Tom Cherry 640bac3299720623f4226bca103b26260052732ad30Tom Cherry Service* svc = ServiceManager::GetInstance().FindServiceByName(name); 641bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc) { 642bac3299720623f4226bca103b26260052732ad30Tom Cherry *err = android::base::StringPrintf("ignored duplicate definition of service '%s'\n", 643bac3299720623f4226bca103b26260052732ad30Tom Cherry name.c_str()); 644bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 645bac3299720623f4226bca103b26260052732ad30Tom Cherry } 646bac3299720623f4226bca103b26260052732ad30Tom Cherry 647bac3299720623f4226bca103b26260052732ad30Tom Cherry std::unique_ptr<Service> svc_p(new Service(name, classname, args)); 648bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!svc_p) { 649bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Couldn't allocate service for service '%s'", name.c_str()); 650bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 651bac3299720623f4226bca103b26260052732ad30Tom Cherry } 652bac3299720623f4226bca103b26260052732ad30Tom Cherry svc = svc_p.get(); 653bac3299720623f4226bca103b26260052732ad30Tom Cherry services_.push_back(std::move(svc_p)); 654bac3299720623f4226bca103b26260052732ad30Tom Cherry 655bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc; 656bac3299720623f4226bca103b26260052732ad30Tom Cherry} 657bac3299720623f4226bca103b26260052732ad30Tom Cherry 658bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::MakeExecOneshotService(const std::vector<std::string>& args) { 659bac3299720623f4226bca103b26260052732ad30Tom Cherry // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS... 660bac3299720623f4226bca103b26260052732ad30Tom Cherry // SECLABEL can be a - to denote default 661bac3299720623f4226bca103b26260052732ad30Tom Cherry std::size_t command_arg = 1; 662bac3299720623f4226bca103b26260052732ad30Tom Cherry for (std::size_t i = 1; i < args.size(); ++i) { 663bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args[i] == "--") { 664bac3299720623f4226bca103b26260052732ad30Tom Cherry command_arg = i + 1; 665bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 666bac3299720623f4226bca103b26260052732ad30Tom Cherry } 667bac3299720623f4226bca103b26260052732ad30Tom Cherry } 668bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 4 + NR_SVC_SUPP_GIDS) { 669bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("exec called with too many supplementary group ids\n"); 670bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 671bac3299720623f4226bca103b26260052732ad30Tom Cherry } 672bac3299720623f4226bca103b26260052732ad30Tom Cherry 673bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg >= args.size()) { 674bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("exec called without command\n"); 675bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 676bac3299720623f4226bca103b26260052732ad30Tom Cherry } 677bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<std::string> str_args(args.begin() + command_arg, args.end()); 678bac3299720623f4226bca103b26260052732ad30Tom Cherry 679bac3299720623f4226bca103b26260052732ad30Tom Cherry exec_count_++; 680bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string name = android::base::StringPrintf("exec %d (%s)", exec_count_, 681bac3299720623f4226bca103b26260052732ad30Tom Cherry str_args[0].c_str()); 682bac3299720623f4226bca103b26260052732ad30Tom Cherry unsigned flags = SVC_EXEC | SVC_ONESHOT; 683bac3299720623f4226bca103b26260052732ad30Tom Cherry 684bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string seclabel = ""; 685bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 2 && args[1] != "-") { 686bac3299720623f4226bca103b26260052732ad30Tom Cherry seclabel = args[1]; 687bac3299720623f4226bca103b26260052732ad30Tom Cherry } 688bac3299720623f4226bca103b26260052732ad30Tom Cherry uid_t uid = 0; 689bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 3) { 690bac3299720623f4226bca103b26260052732ad30Tom Cherry uid = decode_uid(args[2].c_str()); 691bac3299720623f4226bca103b26260052732ad30Tom Cherry } 692bac3299720623f4226bca103b26260052732ad30Tom Cherry gid_t gid = 0; 693bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<gid_t> supp_gids; 694bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 4) { 695bac3299720623f4226bca103b26260052732ad30Tom Cherry gid = decode_uid(args[3].c_str()); 696bac3299720623f4226bca103b26260052732ad30Tom Cherry std::size_t nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */; 697bac3299720623f4226bca103b26260052732ad30Tom Cherry for (size_t i = 0; i < nr_supp_gids; ++i) { 698bac3299720623f4226bca103b26260052732ad30Tom Cherry supp_gids.push_back(decode_uid(args[4 + i].c_str())); 699bac3299720623f4226bca103b26260052732ad30Tom Cherry } 700bac3299720623f4226bca103b26260052732ad30Tom Cherry } 701bac3299720623f4226bca103b26260052732ad30Tom Cherry 702bac3299720623f4226bca103b26260052732ad30Tom Cherry std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid, 703bac3299720623f4226bca103b26260052732ad30Tom Cherry supp_gids, seclabel, str_args)); 704bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!svc_p) { 705bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Couldn't allocate service for exec of '%s'", 706bac3299720623f4226bca103b26260052732ad30Tom Cherry str_args[0].c_str()); 707bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 708bac3299720623f4226bca103b26260052732ad30Tom Cherry } 709bac3299720623f4226bca103b26260052732ad30Tom Cherry Service* svc = svc_p.get(); 710bac3299720623f4226bca103b26260052732ad30Tom Cherry services_.push_back(std::move(svc_p)); 711bac3299720623f4226bca103b26260052732ad30Tom Cherry 712bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc; 713bac3299720623f4226bca103b26260052732ad30Tom Cherry} 714bac3299720623f4226bca103b26260052732ad30Tom Cherry 715bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByName(const std::string& name) const { 716bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 717bac3299720623f4226bca103b26260052732ad30Tom Cherry [&name] (const std::unique_ptr<Service>& s) { 718bac3299720623f4226bca103b26260052732ad30Tom Cherry return name == s->name(); 719bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 720bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 721bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 722bac3299720623f4226bca103b26260052732ad30Tom Cherry } 723bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 724bac3299720623f4226bca103b26260052732ad30Tom Cherry} 725bac3299720623f4226bca103b26260052732ad30Tom Cherry 726bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByPid(pid_t pid) const { 727bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 728bac3299720623f4226bca103b26260052732ad30Tom Cherry [&pid] (const std::unique_ptr<Service>& s) { 729bac3299720623f4226bca103b26260052732ad30Tom Cherry return s->pid() == pid; 730bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 731bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 732bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 733bac3299720623f4226bca103b26260052732ad30Tom Cherry } 734bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 735bac3299720623f4226bca103b26260052732ad30Tom Cherry} 736bac3299720623f4226bca103b26260052732ad30Tom Cherry 737bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByKeychord(int keychord_id) const { 738bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 739bac3299720623f4226bca103b26260052732ad30Tom Cherry [&keychord_id] (const std::unique_ptr<Service>& s) { 740bac3299720623f4226bca103b26260052732ad30Tom Cherry return s->keychord_id() == keychord_id; 741bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 742bac3299720623f4226bca103b26260052732ad30Tom Cherry 743bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 744bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 745bac3299720623f4226bca103b26260052732ad30Tom Cherry } 746bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 747bac3299720623f4226bca103b26260052732ad30Tom Cherry} 748bac3299720623f4226bca103b26260052732ad30Tom Cherry 749bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachService(void (*func)(Service* svc)) const { 750bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 751bac3299720623f4226bca103b26260052732ad30Tom Cherry func(s.get()); 752bac3299720623f4226bca103b26260052732ad30Tom Cherry } 753bac3299720623f4226bca103b26260052732ad30Tom Cherry} 754bac3299720623f4226bca103b26260052732ad30Tom Cherry 755bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachServiceInClass(const std::string& classname, 756bac3299720623f4226bca103b26260052732ad30Tom Cherry void (*func)(Service* svc)) const { 757bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 758bac3299720623f4226bca103b26260052732ad30Tom Cherry if (classname == s->classname()) { 759bac3299720623f4226bca103b26260052732ad30Tom Cherry func(s.get()); 760bac3299720623f4226bca103b26260052732ad30Tom Cherry } 761bac3299720623f4226bca103b26260052732ad30Tom Cherry } 762bac3299720623f4226bca103b26260052732ad30Tom Cherry} 763bac3299720623f4226bca103b26260052732ad30Tom Cherry 764bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachServiceWithFlags(unsigned matchflags, 765bac3299720623f4226bca103b26260052732ad30Tom Cherry void (*func)(Service* svc)) const { 766bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 767bac3299720623f4226bca103b26260052732ad30Tom Cherry if (s->flags() & matchflags) { 768bac3299720623f4226bca103b26260052732ad30Tom Cherry func(s.get()); 769bac3299720623f4226bca103b26260052732ad30Tom Cherry } 770bac3299720623f4226bca103b26260052732ad30Tom Cherry } 771bac3299720623f4226bca103b26260052732ad30Tom Cherry} 772bac3299720623f4226bca103b26260052732ad30Tom Cherry 773bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::RemoveService(const Service& svc) 774bac3299720623f4226bca103b26260052732ad30Tom Cherry{ 775bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc_it = std::find_if(services_.begin(), services_.end(), 776bac3299720623f4226bca103b26260052732ad30Tom Cherry [&svc] (const std::unique_ptr<Service>& s) { 777bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc.name() == s->name(); 778bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 779bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc_it == services_.end()) { 780bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 781bac3299720623f4226bca103b26260052732ad30Tom Cherry } 782bac3299720623f4226bca103b26260052732ad30Tom Cherry 783bac3299720623f4226bca103b26260052732ad30Tom Cherry services_.erase(svc_it); 784bac3299720623f4226bca103b26260052732ad30Tom Cherry} 785bac3299720623f4226bca103b26260052732ad30Tom Cherry 786bac3299720623f4226bca103b26260052732ad30Tom Cherrybool ServiceManager::IsValidName(const std::string& name) const 787bac3299720623f4226bca103b26260052732ad30Tom Cherry{ 788bac3299720623f4226bca103b26260052732ad30Tom Cherry if (name.size() > 16) { 789bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 790bac3299720623f4226bca103b26260052732ad30Tom Cherry } 791bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& c : name) { 792bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!isalnum(c) && (c != '_') && (c != '-')) { 793bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 794bac3299720623f4226bca103b26260052732ad30Tom Cherry } 795bac3299720623f4226bca103b26260052732ad30Tom Cherry } 796bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 797bac3299720623f4226bca103b26260052732ad30Tom Cherry} 798bac3299720623f4226bca103b26260052732ad30Tom Cherry 799bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::DumpState() const 800bac3299720623f4226bca103b26260052732ad30Tom Cherry{ 801bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 802bac3299720623f4226bca103b26260052732ad30Tom Cherry s->DumpState(); 803bac3299720623f4226bca103b26260052732ad30Tom Cherry } 804bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("\n"); 805bac3299720623f4226bca103b26260052732ad30Tom Cherry} 806