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