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