service.cpp revision 1b3fa3d6506d04570aab60147b0ec743e38c8796
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>
201b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes#include <sched.h>
211b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes#include <sys/mount.h>
221b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes#include <sys/prctl.h>
23081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv#include <sys/resource.h>
24bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <sys/stat.h>
25081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv#include <sys/time.h>
26bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <sys/types.h>
27b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET#include <sys/wait.h>
28bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <termios.h>
29af9ba4dc6ca98e136e887b0baa59b72fb8302dd3Dan Albert#include <unistd.h>
30bac3299720623f4226bca103b26260052732ad30Tom Cherry
31bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <selinux/selinux.h>
32bac3299720623f4226bca103b26260052732ad30Tom Cherry
334f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/file.h>
344f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h>
35f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes#include <android-base/strings.h>
36bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <cutils/android_reboot.h>
37bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <cutils/sockets.h>
38081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv#include <system/thread_defs.h>
39bac3299720623f4226bca103b26260052732ad30Tom Cherry
40f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner#include <processgroup/processgroup.h>
41f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner
42bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "action.h"
43bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "init.h"
44bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "init_parser.h"
45bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "log.h"
46bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "property_service.h"
47bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "util.h"
48bac3299720623f4226bca103b26260052732ad30Tom Cherry
49b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryusing android::base::StringPrintf;
50b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryusing android::base::WriteStringToFile;
51b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
52bac3299720623f4226bca103b26260052732ad30Tom Cherry#define CRITICAL_CRASH_THRESHOLD    4       // if we crash >4 times ...
53bac3299720623f4226bca103b26260052732ad30Tom Cherry#define CRITICAL_CRASH_WINDOW       (4*60)  // ... in 4 minutes, goto recovery
54bac3299720623f4226bca103b26260052732ad30Tom Cherry
551b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obesstatic void SetUpPidNamespace(const std::string& service_name) {
561b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    constexpr unsigned int kSafeFlags = MS_NODEV | MS_NOEXEC | MS_NOSUID;
571b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
581b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    // It's OK to LOG(FATAL) in this function since it's running in the first
591b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    // child process.
601b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    if (mount("", "/proc", "proc", kSafeFlags | MS_REMOUNT, "") == -1) {
611b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        PLOG(FATAL) << "couldn't remount(/proc)";
621b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    }
631b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
641b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    if (prctl(PR_SET_NAME, service_name.c_str()) == -1) {
651b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        PLOG(FATAL) << "couldn't set name";
661b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    }
671b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
681b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    pid_t child_pid = fork();
691b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    if (child_pid == -1) {
701b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        PLOG(FATAL) << "couldn't fork init inside the PID namespace";
711b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    }
721b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
731b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    if (child_pid > 0) {
741b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        // So that we exit with the right status.
751b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        static int init_exitstatus = 0;
761b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        signal(SIGTERM, [](int) { _exit(init_exitstatus); });
771b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
781b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        pid_t waited_pid;
791b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        int status;
801b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        while ((waited_pid = wait(&status)) > 0) {
811b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes             // This loop will end when there are no processes left inside the
821b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes             // PID namespace or when the init process inside the PID namespace
831b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes             // gets a signal.
841b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            if (waited_pid == child_pid) {
851b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes                init_exitstatus = status;
861b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            }
871b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        }
881b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        if (!WIFEXITED(init_exitstatus)) {
891b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            _exit(EXIT_FAILURE);
901b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        }
911b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        _exit(WEXITSTATUS(init_exitstatus));
921b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    }
931b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes}
941b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
95bac3299720623f4226bca103b26260052732ad30Tom CherrySocketInfo::SocketInfo() : uid(0), gid(0), perm(0) {
96bac3299720623f4226bca103b26260052732ad30Tom Cherry}
97bac3299720623f4226bca103b26260052732ad30Tom Cherry
98bac3299720623f4226bca103b26260052732ad30Tom CherrySocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid,
99bac3299720623f4226bca103b26260052732ad30Tom Cherry                       gid_t gid, int perm, const std::string& socketcon)
100bac3299720623f4226bca103b26260052732ad30Tom Cherry    : name(name), type(type), uid(uid), gid(gid), perm(perm), socketcon(socketcon) {
101bac3299720623f4226bca103b26260052732ad30Tom Cherry}
102bac3299720623f4226bca103b26260052732ad30Tom Cherry
103bac3299720623f4226bca103b26260052732ad30Tom CherryServiceEnvironmentInfo::ServiceEnvironmentInfo() {
104bac3299720623f4226bca103b26260052732ad30Tom Cherry}
105bac3299720623f4226bca103b26260052732ad30Tom Cherry
106bac3299720623f4226bca103b26260052732ad30Tom CherryServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name,
107bac3299720623f4226bca103b26260052732ad30Tom Cherry                                               const std::string& value)
108bac3299720623f4226bca103b26260052732ad30Tom Cherry    : name(name), value(value) {
109bac3299720623f4226bca103b26260052732ad30Tom Cherry}
110bac3299720623f4226bca103b26260052732ad30Tom Cherry
111bac3299720623f4226bca103b26260052732ad30Tom CherryService::Service(const std::string& name, const std::string& classname,
112bac3299720623f4226bca103b26260052732ad30Tom Cherry                 const std::vector<std::string>& args)
113bac3299720623f4226bca103b26260052732ad30Tom Cherry    : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0),
1141b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes      time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), namespace_flags_(0),
1151b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes      seclabel_(""), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
1161b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes      priority_(0), args_(args) {
117bac3299720623f4226bca103b26260052732ad30Tom Cherry    onrestart_.InitSingleTrigger("onrestart");
118bac3299720623f4226bca103b26260052732ad30Tom Cherry}
119bac3299720623f4226bca103b26260052732ad30Tom Cherry
120bac3299720623f4226bca103b26260052732ad30Tom CherryService::Service(const std::string& name, const std::string& classname,
1211b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes                 unsigned flags, uid_t uid, gid_t gid,
1221b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
1231b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes                 const std::string& seclabel,
1241b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes                 const std::vector<std::string>& args)
1251b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    : name_(name), classname_(classname), flags_(flags), pid_(0),
1261b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes      time_started_(0), time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid),
1271b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes      supp_gids_(supp_gids), namespace_flags_(namespace_flags),
1281b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes      seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
1291b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes      priority_(0), args_(args) {
130bac3299720623f4226bca103b26260052732ad30Tom Cherry    onrestart_.InitSingleTrigger("onrestart");
131bac3299720623f4226bca103b26260052732ad30Tom Cherry}
132bac3299720623f4226bca103b26260052732ad30Tom Cherry
133bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::NotifyStateChange(const std::string& new_state) const {
134bac3299720623f4226bca103b26260052732ad30Tom Cherry    if ((flags_ & SVC_EXEC) != 0) {
135bac3299720623f4226bca103b26260052732ad30Tom Cherry        // 'exec' commands don't have properties tracking their state.
136bac3299720623f4226bca103b26260052732ad30Tom Cherry        return;
137bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
138bac3299720623f4226bca103b26260052732ad30Tom Cherry
139b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    std::string prop_name = StringPrintf("init.svc.%s", name_.c_str());
140bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (prop_name.length() >= PROP_NAME_MAX) {
141bac3299720623f4226bca103b26260052732ad30Tom Cherry        // If the property name would be too long, we can't set it.
142f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(ERROR) << "Property name \"init.svc." << name_ << "\" too long; not setting to " << new_state;
143bac3299720623f4226bca103b26260052732ad30Tom Cherry        return;
144bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
145bac3299720623f4226bca103b26260052732ad30Tom Cherry
146bac3299720623f4226bca103b26260052732ad30Tom Cherry    property_set(prop_name.c_str(), new_state.c_str());
147bac3299720623f4226bca103b26260052732ad30Tom Cherry}
148bac3299720623f4226bca103b26260052732ad30Tom Cherry
149ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughesvoid Service::KillProcessGroup(int signal) {
150f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    LOG(VERBOSE) << "Sending signal " << signal
151f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                 << " to service '" << name_
152f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                 << "' (pid " << pid_ << ") process group...\n",
153ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes    kill(pid_, signal);
154ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes    killProcessGroup(uid_, pid_, signal);
155ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes}
156ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes
157bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Reap() {
158bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
159ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes        KillProcessGroup(SIGKILL);
160bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
161bac3299720623f4226bca103b26260052732ad30Tom Cherry
162bac3299720623f4226bca103b26260052732ad30Tom Cherry    // Remove any sockets we may have created.
163bac3299720623f4226bca103b26260052732ad30Tom Cherry    for (const auto& si : sockets_) {
164b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str());
165bac3299720623f4226bca103b26260052732ad30Tom Cherry        unlink(tmp.c_str());
166bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
167bac3299720623f4226bca103b26260052732ad30Tom Cherry
168bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (flags_ & SVC_EXEC) {
169f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(INFO) << "SVC_EXEC pid " << pid_ << " finished...";
170bac3299720623f4226bca103b26260052732ad30Tom Cherry        return true;
171bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
172bac3299720623f4226bca103b26260052732ad30Tom Cherry
173bac3299720623f4226bca103b26260052732ad30Tom Cherry    pid_ = 0;
174bac3299720623f4226bca103b26260052732ad30Tom Cherry    flags_ &= (~SVC_RUNNING);
175bac3299720623f4226bca103b26260052732ad30Tom Cherry
176bac3299720623f4226bca103b26260052732ad30Tom Cherry    // Oneshot processes go into the disabled state on exit,
177bac3299720623f4226bca103b26260052732ad30Tom Cherry    // except when manually restarted.
178bac3299720623f4226bca103b26260052732ad30Tom Cherry    if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) {
179bac3299720623f4226bca103b26260052732ad30Tom Cherry        flags_ |= SVC_DISABLED;
180bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
181bac3299720623f4226bca103b26260052732ad30Tom Cherry
182bac3299720623f4226bca103b26260052732ad30Tom Cherry    // Disabled and reset processes do not get restarted automatically.
183bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (flags_ & (SVC_DISABLED | SVC_RESET))  {
184bac3299720623f4226bca103b26260052732ad30Tom Cherry        NotifyStateChange("stopped");
185bac3299720623f4226bca103b26260052732ad30Tom Cherry        return false;
186bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
187bac3299720623f4226bca103b26260052732ad30Tom Cherry
188bac3299720623f4226bca103b26260052732ad30Tom Cherry    time_t now = gettime();
189bac3299720623f4226bca103b26260052732ad30Tom Cherry    if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
190bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (time_crashed_ + CRITICAL_CRASH_WINDOW >= now) {
191bac3299720623f4226bca103b26260052732ad30Tom Cherry            if (++nr_crashed_ > CRITICAL_CRASH_THRESHOLD) {
192f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                LOG(ERROR) << "critical process '" << name_ << "' exited "
193f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                           << CRITICAL_CRASH_THRESHOLD << " times in "
194f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                           << (CRITICAL_CRASH_WINDOW / 60) << " minutes; "
195f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                           << "rebooting into recovery mode";
196bac3299720623f4226bca103b26260052732ad30Tom Cherry                android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
197bac3299720623f4226bca103b26260052732ad30Tom Cherry                return false;
198bac3299720623f4226bca103b26260052732ad30Tom Cherry            }
199bac3299720623f4226bca103b26260052732ad30Tom Cherry        } else {
200bac3299720623f4226bca103b26260052732ad30Tom Cherry            time_crashed_ = now;
201bac3299720623f4226bca103b26260052732ad30Tom Cherry            nr_crashed_ = 1;
202bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
203bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
204bac3299720623f4226bca103b26260052732ad30Tom Cherry
205bac3299720623f4226bca103b26260052732ad30Tom Cherry    flags_ &= (~SVC_RESTART);
206bac3299720623f4226bca103b26260052732ad30Tom Cherry    flags_ |= SVC_RESTARTING;
207bac3299720623f4226bca103b26260052732ad30Tom Cherry
208bac3299720623f4226bca103b26260052732ad30Tom Cherry    // Execute all onrestart commands for this service.
209bac3299720623f4226bca103b26260052732ad30Tom Cherry    onrestart_.ExecuteAllCommands();
210bac3299720623f4226bca103b26260052732ad30Tom Cherry
211bac3299720623f4226bca103b26260052732ad30Tom Cherry    NotifyStateChange("restarting");
212bac3299720623f4226bca103b26260052732ad30Tom Cherry    return false;
213bac3299720623f4226bca103b26260052732ad30Tom Cherry}
214bac3299720623f4226bca103b26260052732ad30Tom Cherry
215bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::DumpState() const {
216f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    LOG(INFO) << "service " << name_;
217f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    LOG(INFO) << "  class '" << classname_ << "'";
218f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    LOG(INFO) << "  exec "<< android::base::Join(args_, " ");
219bac3299720623f4226bca103b26260052732ad30Tom Cherry    for (const auto& si : sockets_) {
220f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(INFO) << "  socket " << si.name << " " << si.type << " " << std::oct << si.perm;
221bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
222bac3299720623f4226bca103b26260052732ad30Tom Cherry}
223bac3299720623f4226bca103b26260052732ad30Tom Cherry
224b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleClass(const std::vector<std::string>& args, std::string* err) {
225b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    classname_ = args[1];
226b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
227b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
228bac3299720623f4226bca103b26260052732ad30Tom Cherry
229b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) {
230b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    flags_ |= SVC_CONSOLE;
23170daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman    console_ = args.size() > 1 ? "/dev/" + args[1] : "";
232b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
233b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
234bac3299720623f4226bca103b26260052732ad30Tom Cherry
235b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleCritical(const std::vector<std::string>& args, std::string* err) {
236b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    flags_ |= SVC_CRITICAL;
237b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
238b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
239bac3299720623f4226bca103b26260052732ad30Tom Cherry
240b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleDisabled(const std::vector<std::string>& args, std::string* err) {
241b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    flags_ |= SVC_DISABLED;
242b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    flags_ |= SVC_RC_DISABLED;
243b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
244b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
245bac3299720623f4226bca103b26260052732ad30Tom Cherry
246b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleGroup(const std::vector<std::string>& args, std::string* err) {
247b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    gid_ = decode_uid(args[1].c_str());
248b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    for (std::size_t n = 2; n < args.size(); n++) {
249b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        supp_gids_.emplace_back(decode_uid(args[n].c_str()));
250b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
251b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
252b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
253bac3299720623f4226bca103b26260052732ad30Tom Cherry
254081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkivbool Service::HandlePriority(const std::vector<std::string>& args, std::string* err) {
255081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv    priority_ = std::stoi(args[1]);
256081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv
257081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv    if (priority_ < ANDROID_PRIORITY_HIGHEST || priority_ > ANDROID_PRIORITY_LOWEST) {
258081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv        priority_ = 0;
259081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv        *err = StringPrintf("process priority value must be range %d - %d",
260081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv                ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST);
261081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv        return false;
262081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv    }
263081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv
264081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv    return true;
265081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv}
266081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv
267b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleIoprio(const std::vector<std::string>& args, std::string* err) {
268b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    ioprio_pri_ = std::stoul(args[2], 0, 8);
269b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
270b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (ioprio_pri_ < 0 || ioprio_pri_ > 7) {
271b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        *err = "priority value must be range 0 - 7";
272b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        return false;
273b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
274b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
275b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (args[1] == "rt") {
276b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        ioprio_class_ = IoSchedClass_RT;
277b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    } else if (args[1] == "be") {
278b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        ioprio_class_ = IoSchedClass_BE;
279b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    } else if (args[1] == "idle") {
280b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        ioprio_class_ = IoSchedClass_IDLE;
281b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    } else {
282b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        *err = "ioprio option usage: ioprio <rt|be|idle> <0-7>";
283b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        return false;
284bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
285bac3299720623f4226bca103b26260052732ad30Tom Cherry
286b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
287b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
288bac3299720623f4226bca103b26260052732ad30Tom Cherry
289b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleKeycodes(const std::vector<std::string>& args, std::string* err) {
290b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    for (std::size_t i = 1; i < args.size(); i++) {
291b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        keycodes_.emplace_back(std::stoi(args[i]));
292bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
293b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
294b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
295b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
296b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleOneshot(const std::vector<std::string>& args, std::string* err) {
297b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    flags_ |= SVC_ONESHOT;
298b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
299b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
300b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
301b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleOnrestart(const std::vector<std::string>& args, std::string* err) {
302b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    std::vector<std::string> str_args(args.begin() + 1, args.end());
303b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    onrestart_.AddCommand(str_args, "", 0, err);
304b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
305b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
306bac3299720623f4226bca103b26260052732ad30Tom Cherry
3071b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obesbool Service::HandleNamespace(const std::vector<std::string>& args, std::string* err) {
3081b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    for (size_t i = 1; i < args.size(); i++) {
3091b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        if (args[i] == "pid") {
3101b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            namespace_flags_ |= CLONE_NEWPID;
3111b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            // PID namespaces require mount namespaces.
3121b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            namespace_flags_ |= CLONE_NEWNS;
3131b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        } else if (args[i] == "mnt") {
3141b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            namespace_flags_ |= CLONE_NEWNS;
3151b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        } else {
3161b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            *err = "namespace must be 'pid' or 'mnt'";
3171b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            return false;
3181b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        }
3191b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    }
3201b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    return true;
3211b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes}
3221b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
323b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSeclabel(const std::vector<std::string>& args, std::string* err) {
324b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    seclabel_ = args[1];
325b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
326b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
327b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
328b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSetenv(const std::vector<std::string>& args, std::string* err) {
329b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    envvars_.emplace_back(args[1], args[2]);
330b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
331b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
332b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
333b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry/* name type perm [ uid gid context ] */
334b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSocket(const std::vector<std::string>& args, std::string* err) {
335b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") {
336b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        *err = "socket type must be 'dgram', 'stream' or 'seqpacket'";
337bac3299720623f4226bca103b26260052732ad30Tom Cherry        return false;
338bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
339b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
340b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    int perm = std::stoul(args[3], 0, 8);
341b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0;
342b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0;
343b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    std::string socketcon = args.size() > 6 ? args[6] : "";
344b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
345b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    sockets_.emplace_back(args[1], args[2], uid, gid, perm, socketcon);
346bac3299720623f4226bca103b26260052732ad30Tom Cherry    return true;
347bac3299720623f4226bca103b26260052732ad30Tom Cherry}
348bac3299720623f4226bca103b26260052732ad30Tom Cherry
349b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleUser(const std::vector<std::string>& args, std::string* err) {
350b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    uid_ = decode_uid(args[1].c_str());
351b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
352b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
353b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
354b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleWritepid(const std::vector<std::string>& args, std::string* err) {
355b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    writepid_files_.assign(args.begin() + 1, args.end());
356b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
357b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
358b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
359b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryclass Service::OptionHandlerMap : public KeywordMap<OptionHandler> {
360b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrypublic:
361b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    OptionHandlerMap() {
362b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
363b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryprivate:
364b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    Map& map() const override;
365b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry};
366b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
367b7349902a945903f9e36a569051f5131beb0bc24Tom CherryService::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
368b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
369b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    static const Map option_handlers = {
370b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"class",       {1,     1,    &Service::HandleClass}},
37170daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman        {"console",     {0,     1,    &Service::HandleConsole}},
372b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"critical",    {0,     0,    &Service::HandleCritical}},
373b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"disabled",    {0,     0,    &Service::HandleDisabled}},
374b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
375b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"ioprio",      {2,     2,    &Service::HandleIoprio}},
376081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv        {"priority",    {1,     1,    &Service::HandlePriority}},
377b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"keycodes",    {1,     kMax, &Service::HandleKeycodes}},
378b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"oneshot",     {0,     0,    &Service::HandleOneshot}},
379b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"onrestart",   {1,     kMax, &Service::HandleOnrestart}},
3801b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        {"namespace",   {1,     2,    &Service::HandleNamespace}},
381b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"seclabel",    {1,     1,    &Service::HandleSeclabel}},
382b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"setenv",      {2,     2,    &Service::HandleSetenv}},
383b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"socket",      {3,     6,    &Service::HandleSocket}},
384b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"user",        {1,     1,    &Service::HandleUser}},
385b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        {"writepid",    {1,     kMax, &Service::HandleWritepid}},
386b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    };
387b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return option_handlers;
388b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
389b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
390b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleLine(const std::vector<std::string>& args, std::string* err) {
391b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (args.empty()) {
392b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        *err = "option needed, but not provided";
393b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        return false;
394b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
395b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
396b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    static const OptionHandlerMap handler_map;
397b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    auto handler = handler_map.FindFunction(args[0], args.size() - 1, err);
398b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
399b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (!handler) {
400b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        return false;
401b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
402b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
403b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return (this->*handler)(args, err);
404b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
405b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
406bdeac39a42c1b9c7195ada1c30fe12f94314490fElliott Hughesbool Service::Start() {
407bac3299720623f4226bca103b26260052732ad30Tom Cherry    // Starting a service removes it from the disabled or reset state and
408bac3299720623f4226bca103b26260052732ad30Tom Cherry    // immediately takes it out of the restarting state if it was in there.
409bac3299720623f4226bca103b26260052732ad30Tom Cherry    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
410bac3299720623f4226bca103b26260052732ad30Tom Cherry    time_started_ = 0;
411bac3299720623f4226bca103b26260052732ad30Tom Cherry
412bac3299720623f4226bca103b26260052732ad30Tom Cherry    // Running processes require no additional work --- if they're in the
413bac3299720623f4226bca103b26260052732ad30Tom Cherry    // process of exiting, we've ensured that they will immediately restart
414bac3299720623f4226bca103b26260052732ad30Tom Cherry    // on exit, unless they are ONESHOT.
415bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (flags_ & SVC_RUNNING) {
416bac3299720623f4226bca103b26260052732ad30Tom Cherry        return false;
417bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
418bac3299720623f4226bca103b26260052732ad30Tom Cherry
419bac3299720623f4226bca103b26260052732ad30Tom Cherry    bool needs_console = (flags_ & SVC_CONSOLE);
42070daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman    if (needs_console) {
42170daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman        if (console_.empty()) {
42270daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman            console_ = default_console;
42370daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman        }
42470daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman
42570daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman        bool have_console = (open(console_.c_str(), O_RDWR | O_CLOEXEC) != -1);
42670daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman        if (!have_console) {
427f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes            PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'";
42870daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman            flags_ |= SVC_DISABLED;
42970daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman            return false;
43070daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman        }
431bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
432bac3299720623f4226bca103b26260052732ad30Tom Cherry
433bac3299720623f4226bca103b26260052732ad30Tom Cherry    struct stat sb;
434bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (stat(args_[0].c_str(), &sb) == -1) {
435f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
436bac3299720623f4226bca103b26260052732ad30Tom Cherry        flags_ |= SVC_DISABLED;
437bac3299720623f4226bca103b26260052732ad30Tom Cherry        return false;
438bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
439bac3299720623f4226bca103b26260052732ad30Tom Cherry
440bac3299720623f4226bca103b26260052732ad30Tom Cherry    std::string scon;
441bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (!seclabel_.empty()) {
442bac3299720623f4226bca103b26260052732ad30Tom Cherry        scon = seclabel_;
443bac3299720623f4226bca103b26260052732ad30Tom Cherry    } else {
444bac3299720623f4226bca103b26260052732ad30Tom Cherry        char* mycon = nullptr;
445bac3299720623f4226bca103b26260052732ad30Tom Cherry        char* fcon = nullptr;
446bac3299720623f4226bca103b26260052732ad30Tom Cherry
447f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(INFO) << "computing context for service '" << args_[0] << "'";
448bac3299720623f4226bca103b26260052732ad30Tom Cherry        int rc = getcon(&mycon);
449bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (rc < 0) {
450f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes            LOG(ERROR) << "could not get context while starting '" << name_ << "'";
451bac3299720623f4226bca103b26260052732ad30Tom Cherry            return false;
452bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
453bac3299720623f4226bca103b26260052732ad30Tom Cherry
454bac3299720623f4226bca103b26260052732ad30Tom Cherry        rc = getfilecon(args_[0].c_str(), &fcon);
455bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (rc < 0) {
4561b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            LOG(ERROR) << "could not get file context while starting '" << name_ << "'";
457bac3299720623f4226bca103b26260052732ad30Tom Cherry            free(mycon);
458bac3299720623f4226bca103b26260052732ad30Tom Cherry            return false;
459bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
460bac3299720623f4226bca103b26260052732ad30Tom Cherry
461bac3299720623f4226bca103b26260052732ad30Tom Cherry        char* ret_scon = nullptr;
462bac3299720623f4226bca103b26260052732ad30Tom Cherry        rc = security_compute_create(mycon, fcon, string_to_security_class("process"),
463bac3299720623f4226bca103b26260052732ad30Tom Cherry                                     &ret_scon);
464bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (rc == 0) {
465bac3299720623f4226bca103b26260052732ad30Tom Cherry            scon = ret_scon;
466bac3299720623f4226bca103b26260052732ad30Tom Cherry            free(ret_scon);
467bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
468bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (rc == 0 && scon == mycon) {
469f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes            LOG(ERROR) << "Service " << name_ << " does not have a SELinux domain defined.";
470bac3299720623f4226bca103b26260052732ad30Tom Cherry            free(mycon);
471bac3299720623f4226bca103b26260052732ad30Tom Cherry            free(fcon);
472bac3299720623f4226bca103b26260052732ad30Tom Cherry            return false;
473bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
474bac3299720623f4226bca103b26260052732ad30Tom Cherry        free(mycon);
475bac3299720623f4226bca103b26260052732ad30Tom Cherry        free(fcon);
476bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (rc < 0) {
477f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes            LOG(ERROR) << "could not get context while starting '" << name_ << "'";
478bac3299720623f4226bca103b26260052732ad30Tom Cherry            return false;
479bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
480bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
481bac3299720623f4226bca103b26260052732ad30Tom Cherry
482f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    LOG(VERBOSE) << "Starting service '" << name_ << "'...";
483bac3299720623f4226bca103b26260052732ad30Tom Cherry
4841b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    pid_t pid = -1;
4851b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    if (namespace_flags_) {
4861b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD,
4871b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes                    nullptr);
4881b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    } else {
4891b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        pid = fork();
4901b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    }
4911b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
492bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (pid == 0) {
493bac3299720623f4226bca103b26260052732ad30Tom Cherry        umask(077);
494bac3299720623f4226bca103b26260052732ad30Tom Cherry
4951b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        if (namespace_flags_ & CLONE_NEWPID) {
4961b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            // This will fork again to run an init process inside the PID
4971b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            // namespace.
4981b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes            SetUpPidNamespace(name_);
4991b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes        }
5001b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes
501bac3299720623f4226bca103b26260052732ad30Tom Cherry        for (const auto& ei : envvars_) {
502bac3299720623f4226bca103b26260052732ad30Tom Cherry            add_environment(ei.name.c_str(), ei.value.c_str());
503bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
504bac3299720623f4226bca103b26260052732ad30Tom Cherry
505bac3299720623f4226bca103b26260052732ad30Tom Cherry        for (const auto& si : sockets_) {
506bac3299720623f4226bca103b26260052732ad30Tom Cherry            int socket_type = ((si.type == "stream" ? SOCK_STREAM :
507bac3299720623f4226bca103b26260052732ad30Tom Cherry                                (si.type == "dgram" ? SOCK_DGRAM :
508bac3299720623f4226bca103b26260052732ad30Tom Cherry                                 SOCK_SEQPACKET)));
509bac3299720623f4226bca103b26260052732ad30Tom Cherry            const char* socketcon =
510bac3299720623f4226bca103b26260052732ad30Tom Cherry                !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str();
511bac3299720623f4226bca103b26260052732ad30Tom Cherry
512bac3299720623f4226bca103b26260052732ad30Tom Cherry            int s = create_socket(si.name.c_str(), socket_type, si.perm,
513bac3299720623f4226bca103b26260052732ad30Tom Cherry                                  si.uid, si.gid, socketcon);
514bac3299720623f4226bca103b26260052732ad30Tom Cherry            if (s >= 0) {
515bac3299720623f4226bca103b26260052732ad30Tom Cherry                PublishSocket(si.name, s);
516bac3299720623f4226bca103b26260052732ad30Tom Cherry            }
517bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
518bac3299720623f4226bca103b26260052732ad30Tom Cherry
519b702b46f688bc3ba7f8dc2d35c6eb25482366c4cAnestis Bechtsoudis        std::string pid_str = StringPrintf("%d", getpid());
520bac3299720623f4226bca103b26260052732ad30Tom Cherry        for (const auto& file : writepid_files_) {
521b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry            if (!WriteStringToFile(pid_str, file)) {
522f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                PLOG(ERROR) << "couldn't write " << pid_str << " to " << file;
523bac3299720623f4226bca103b26260052732ad30Tom Cherry            }
524bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
525bac3299720623f4226bca103b26260052732ad30Tom Cherry
526bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (ioprio_class_ != IoSchedClass_NONE) {
527bac3299720623f4226bca103b26260052732ad30Tom Cherry            if (android_set_ioprio(getpid(), ioprio_class_, ioprio_pri_)) {
528f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                PLOG(ERROR) << "Failed to set pid " << getpid()
529f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                            << " ioprio=" << ioprio_class_ << "," << ioprio_pri_;
530bac3299720623f4226bca103b26260052732ad30Tom Cherry            }
531bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
532bac3299720623f4226bca103b26260052732ad30Tom Cherry
533bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (needs_console) {
534bac3299720623f4226bca103b26260052732ad30Tom Cherry            setsid();
535bac3299720623f4226bca103b26260052732ad30Tom Cherry            OpenConsole();
536bac3299720623f4226bca103b26260052732ad30Tom Cherry        } else {
537bac3299720623f4226bca103b26260052732ad30Tom Cherry            ZapStdio();
538bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
539bac3299720623f4226bca103b26260052732ad30Tom Cherry
540bac3299720623f4226bca103b26260052732ad30Tom Cherry        setpgid(0, getpid());
541bac3299720623f4226bca103b26260052732ad30Tom Cherry
542bac3299720623f4226bca103b26260052732ad30Tom Cherry        // As requested, set our gid, supplemental gids, and uid.
543bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (gid_) {
544bac3299720623f4226bca103b26260052732ad30Tom Cherry            if (setgid(gid_) != 0) {
545f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                PLOG(ERROR) << "setgid failed";
546bac3299720623f4226bca103b26260052732ad30Tom Cherry                _exit(127);
547bac3299720623f4226bca103b26260052732ad30Tom Cherry            }
548bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
549bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (!supp_gids_.empty()) {
550bac3299720623f4226bca103b26260052732ad30Tom Cherry            if (setgroups(supp_gids_.size(), &supp_gids_[0]) != 0) {
551f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                PLOG(ERROR) << "setgroups failed";
552bac3299720623f4226bca103b26260052732ad30Tom Cherry                _exit(127);
553bac3299720623f4226bca103b26260052732ad30Tom Cherry            }
554bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
555bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (uid_) {
556bac3299720623f4226bca103b26260052732ad30Tom Cherry            if (setuid(uid_) != 0) {
557f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                PLOG(ERROR) << "setuid failed";
558bac3299720623f4226bca103b26260052732ad30Tom Cherry                _exit(127);
559bac3299720623f4226bca103b26260052732ad30Tom Cherry            }
560bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
561bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (!seclabel_.empty()) {
562bac3299720623f4226bca103b26260052732ad30Tom Cherry            if (setexeccon(seclabel_.c_str()) < 0) {
563f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                PLOG(ERROR) << "cannot setexeccon('" << seclabel_ << "')";
564bac3299720623f4226bca103b26260052732ad30Tom Cherry                _exit(127);
565bac3299720623f4226bca103b26260052732ad30Tom Cherry            }
566bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
567081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv        if (priority_ != 0) {
568081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv            if (setpriority(PRIO_PROCESS, 0, priority_) != 0) {
569f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                PLOG(ERROR) << "setpriority failed";
570081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv                _exit(127);
571081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv            }
572081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv        }
573bac3299720623f4226bca103b26260052732ad30Tom Cherry
574bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry        std::vector<std::string> expanded_args;
575bac3299720623f4226bca103b26260052732ad30Tom Cherry        std::vector<char*> strs;
576bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry        expanded_args.resize(args_.size());
577bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry        strs.push_back(const_cast<char*>(args_[0].c_str()));
578bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry        for (std::size_t i = 1; i < args_.size(); ++i) {
579bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry            if (!expand_props(args_[i], &expanded_args[i])) {
580f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                LOG(ERROR) << args_[0] << ": cannot expand '" << args_[i] << "'";
581bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry                _exit(127);
582bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry            }
583bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry            strs.push_back(const_cast<char*>(expanded_args[i].c_str()));
584bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
585bac3299720623f4226bca103b26260052732ad30Tom Cherry        strs.push_back(nullptr);
586bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry
587bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry        if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
588f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes            PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
589bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
590bac3299720623f4226bca103b26260052732ad30Tom Cherry
591bac3299720623f4226bca103b26260052732ad30Tom Cherry        _exit(127);
592bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
593bac3299720623f4226bca103b26260052732ad30Tom Cherry
594bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (pid < 0) {
595f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        PLOG(ERROR) << "failed to fork for '" << name_ << "'";
596bac3299720623f4226bca103b26260052732ad30Tom Cherry        pid_ = 0;
597bac3299720623f4226bca103b26260052732ad30Tom Cherry        return false;
598bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
599bac3299720623f4226bca103b26260052732ad30Tom Cherry
600bac3299720623f4226bca103b26260052732ad30Tom Cherry    time_started_ = gettime();
601bac3299720623f4226bca103b26260052732ad30Tom Cherry    pid_ = pid;
602bac3299720623f4226bca103b26260052732ad30Tom Cherry    flags_ |= SVC_RUNNING;
603ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes
604ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes    errno = -createProcessGroup(uid_, pid_);
605ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes    if (errno != 0) {
606f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '" << name_ << "'";
607ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes    }
608bac3299720623f4226bca103b26260052732ad30Tom Cherry
609bac3299720623f4226bca103b26260052732ad30Tom Cherry    if ((flags_ & SVC_EXEC) != 0) {
610f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(INFO) << android::base::StringPrintf("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...",
611f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                                                 pid_, uid_, gid_, supp_gids_.size(),
612f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                                                 !seclabel_.empty() ? seclabel_.c_str() : "default");
613bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
614bac3299720623f4226bca103b26260052732ad30Tom Cherry
615bac3299720623f4226bca103b26260052732ad30Tom Cherry    NotifyStateChange("running");
616bac3299720623f4226bca103b26260052732ad30Tom Cherry    return true;
617bac3299720623f4226bca103b26260052732ad30Tom Cherry}
618bac3299720623f4226bca103b26260052732ad30Tom Cherry
619bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::StartIfNotDisabled() {
620bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (!(flags_ & SVC_DISABLED)) {
621bac3299720623f4226bca103b26260052732ad30Tom Cherry        return Start();
622bac3299720623f4226bca103b26260052732ad30Tom Cherry    } else {
623bac3299720623f4226bca103b26260052732ad30Tom Cherry        flags_ |= SVC_DISABLED_START;
624bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
625bac3299720623f4226bca103b26260052732ad30Tom Cherry    return true;
626bac3299720623f4226bca103b26260052732ad30Tom Cherry}
627bac3299720623f4226bca103b26260052732ad30Tom Cherry
628bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Enable() {
629bac3299720623f4226bca103b26260052732ad30Tom Cherry    flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED);
630bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (flags_ & SVC_DISABLED_START) {
631bac3299720623f4226bca103b26260052732ad30Tom Cherry        return Start();
632bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
633bac3299720623f4226bca103b26260052732ad30Tom Cherry    return true;
634bac3299720623f4226bca103b26260052732ad30Tom Cherry}
635bac3299720623f4226bca103b26260052732ad30Tom Cherry
636bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Reset() {
637bac3299720623f4226bca103b26260052732ad30Tom Cherry    StopOrReset(SVC_RESET);
638bac3299720623f4226bca103b26260052732ad30Tom Cherry}
639bac3299720623f4226bca103b26260052732ad30Tom Cherry
640bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Stop() {
641bac3299720623f4226bca103b26260052732ad30Tom Cherry    StopOrReset(SVC_DISABLED);
642bac3299720623f4226bca103b26260052732ad30Tom Cherry}
643bac3299720623f4226bca103b26260052732ad30Tom Cherry
644b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid Service::Terminate() {
645b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START);
646b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    flags_ |= SVC_DISABLED;
647b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    if (pid_) {
648ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes        KillProcessGroup(SIGTERM);
649b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        NotifyStateChange("stopping");
650b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    }
651b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET}
652b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
653bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Restart() {
654bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (flags_ & SVC_RUNNING) {
655bac3299720623f4226bca103b26260052732ad30Tom Cherry        /* Stop, wait, then start the service. */
656bac3299720623f4226bca103b26260052732ad30Tom Cherry        StopOrReset(SVC_RESTART);
657bac3299720623f4226bca103b26260052732ad30Tom Cherry    } else if (!(flags_ & SVC_RESTARTING)) {
658bac3299720623f4226bca103b26260052732ad30Tom Cherry        /* Just start the service since it's not running. */
659bac3299720623f4226bca103b26260052732ad30Tom Cherry        Start();
660bac3299720623f4226bca103b26260052732ad30Tom Cherry    } /* else: Service is restarting anyways. */
661bac3299720623f4226bca103b26260052732ad30Tom Cherry}
662bac3299720623f4226bca103b26260052732ad30Tom Cherry
663bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::RestartIfNeeded(time_t& process_needs_restart) {
664bac3299720623f4226bca103b26260052732ad30Tom Cherry    time_t next_start_time = time_started_ + 5;
665bac3299720623f4226bca103b26260052732ad30Tom Cherry
666bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (next_start_time <= gettime()) {
667bac3299720623f4226bca103b26260052732ad30Tom Cherry        flags_ &= (~SVC_RESTARTING);
668bac3299720623f4226bca103b26260052732ad30Tom Cherry        Start();
669bac3299720623f4226bca103b26260052732ad30Tom Cherry        return;
670bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
671bac3299720623f4226bca103b26260052732ad30Tom Cherry
672bac3299720623f4226bca103b26260052732ad30Tom Cherry    if ((next_start_time < process_needs_restart) ||
673bac3299720623f4226bca103b26260052732ad30Tom Cherry        (process_needs_restart == 0)) {
674bac3299720623f4226bca103b26260052732ad30Tom Cherry        process_needs_restart = next_start_time;
675bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
676bac3299720623f4226bca103b26260052732ad30Tom Cherry}
677bac3299720623f4226bca103b26260052732ad30Tom Cherry
678ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes// The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART.
679bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::StopOrReset(int how) {
680ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes    // The service is still SVC_RUNNING until its process exits, but if it has
681ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes    // already exited it shoudn't attempt a restart yet.
682bac3299720623f4226bca103b26260052732ad30Tom Cherry    flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START);
683bac3299720623f4226bca103b26260052732ad30Tom Cherry
684bac3299720623f4226bca103b26260052732ad30Tom Cherry    if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) {
685ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes        // An illegal flag: default to SVC_DISABLED.
686bac3299720623f4226bca103b26260052732ad30Tom Cherry        how = SVC_DISABLED;
687bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
688ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes
689ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes    // If the service has not yet started, prevent it from auto-starting with its class.
690bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (how == SVC_RESET) {
691bac3299720623f4226bca103b26260052732ad30Tom Cherry        flags_ |= (flags_ & SVC_RC_DISABLED) ? SVC_DISABLED : SVC_RESET;
692bac3299720623f4226bca103b26260052732ad30Tom Cherry    } else {
693bac3299720623f4226bca103b26260052732ad30Tom Cherry        flags_ |= how;
694bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
695bac3299720623f4226bca103b26260052732ad30Tom Cherry
696bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (pid_) {
697ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes        KillProcessGroup(SIGKILL);
698bac3299720623f4226bca103b26260052732ad30Tom Cherry        NotifyStateChange("stopping");
699bac3299720623f4226bca103b26260052732ad30Tom Cherry    } else {
700bac3299720623f4226bca103b26260052732ad30Tom Cherry        NotifyStateChange("stopped");
701bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
702bac3299720623f4226bca103b26260052732ad30Tom Cherry}
703bac3299720623f4226bca103b26260052732ad30Tom Cherry
704bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::ZapStdio() const {
705bac3299720623f4226bca103b26260052732ad30Tom Cherry    int fd;
706bac3299720623f4226bca103b26260052732ad30Tom Cherry    fd = open("/dev/null", O_RDWR);
707bac3299720623f4226bca103b26260052732ad30Tom Cherry    dup2(fd, 0);
708bac3299720623f4226bca103b26260052732ad30Tom Cherry    dup2(fd, 1);
709bac3299720623f4226bca103b26260052732ad30Tom Cherry    dup2(fd, 2);
710bac3299720623f4226bca103b26260052732ad30Tom Cherry    close(fd);
711bac3299720623f4226bca103b26260052732ad30Tom Cherry}
712bac3299720623f4226bca103b26260052732ad30Tom Cherry
713bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::OpenConsole() const {
71470daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman    int fd = open(console_.c_str(), O_RDWR);
71570daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman    if (fd == -1) fd = open("/dev/null", O_RDWR);
716bac3299720623f4226bca103b26260052732ad30Tom Cherry    ioctl(fd, TIOCSCTTY, 0);
717bac3299720623f4226bca103b26260052732ad30Tom Cherry    dup2(fd, 0);
718bac3299720623f4226bca103b26260052732ad30Tom Cherry    dup2(fd, 1);
719bac3299720623f4226bca103b26260052732ad30Tom Cherry    dup2(fd, 2);
720bac3299720623f4226bca103b26260052732ad30Tom Cherry    close(fd);
721bac3299720623f4226bca103b26260052732ad30Tom Cherry}
722bac3299720623f4226bca103b26260052732ad30Tom Cherry
723bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::PublishSocket(const std::string& name, int fd) const {
724b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str());
725b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    std::string val = StringPrintf("%d", fd);
726bac3299720623f4226bca103b26260052732ad30Tom Cherry    add_environment(key.c_str(), val.c_str());
727bac3299720623f4226bca103b26260052732ad30Tom Cherry
728bac3299720623f4226bca103b26260052732ad30Tom Cherry    /* make sure we don't close-on-exec */
729bac3299720623f4226bca103b26260052732ad30Tom Cherry    fcntl(fd, F_SETFD, 0);
730bac3299720623f4226bca103b26260052732ad30Tom Cherry}
731bac3299720623f4226bca103b26260052732ad30Tom Cherry
732bac3299720623f4226bca103b26260052732ad30Tom Cherryint ServiceManager::exec_count_ = 0;
733bac3299720623f4226bca103b26260052732ad30Tom Cherry
734bac3299720623f4226bca103b26260052732ad30Tom CherryServiceManager::ServiceManager() {
735bac3299720623f4226bca103b26260052732ad30Tom Cherry}
736bac3299720623f4226bca103b26260052732ad30Tom Cherry
737bac3299720623f4226bca103b26260052732ad30Tom CherryServiceManager& ServiceManager::GetInstance() {
738bac3299720623f4226bca103b26260052732ad30Tom Cherry    static ServiceManager instance;
739bac3299720623f4226bca103b26260052732ad30Tom Cherry    return instance;
740bac3299720623f4226bca103b26260052732ad30Tom Cherry}
741bac3299720623f4226bca103b26260052732ad30Tom Cherry
742b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::AddService(std::unique_ptr<Service> service) {
743b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    Service* old_service = FindServiceByName(service->name());
744b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (old_service) {
745f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(ERROR) << "ignored duplicate definition of service '" << service->name() << "'";
746b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        return;
747bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
748b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    services_.emplace_back(std::move(service));
749bac3299720623f4226bca103b26260052732ad30Tom Cherry}
750bac3299720623f4226bca103b26260052732ad30Tom Cherry
751bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::MakeExecOneshotService(const std::vector<std::string>& args) {
752bac3299720623f4226bca103b26260052732ad30Tom Cherry    // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS...
753bac3299720623f4226bca103b26260052732ad30Tom Cherry    // SECLABEL can be a - to denote default
754bac3299720623f4226bca103b26260052732ad30Tom Cherry    std::size_t command_arg = 1;
755bac3299720623f4226bca103b26260052732ad30Tom Cherry    for (std::size_t i = 1; i < args.size(); ++i) {
756bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (args[i] == "--") {
757bac3299720623f4226bca103b26260052732ad30Tom Cherry            command_arg = i + 1;
758bac3299720623f4226bca103b26260052732ad30Tom Cherry            break;
759bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
760bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
761bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (command_arg > 4 + NR_SVC_SUPP_GIDS) {
762f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(ERROR) << "exec called with too many supplementary group ids";
763bac3299720623f4226bca103b26260052732ad30Tom Cherry        return nullptr;
764bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
765bac3299720623f4226bca103b26260052732ad30Tom Cherry
766bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (command_arg >= args.size()) {
767f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(ERROR) << "exec called without command";
768bac3299720623f4226bca103b26260052732ad30Tom Cherry        return nullptr;
769bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
770bac3299720623f4226bca103b26260052732ad30Tom Cherry    std::vector<std::string> str_args(args.begin() + command_arg, args.end());
771bac3299720623f4226bca103b26260052732ad30Tom Cherry
772bac3299720623f4226bca103b26260052732ad30Tom Cherry    exec_count_++;
773b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str());
774bac3299720623f4226bca103b26260052732ad30Tom Cherry    unsigned flags = SVC_EXEC | SVC_ONESHOT;
7751b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes    unsigned namespace_flags = 0;
776bac3299720623f4226bca103b26260052732ad30Tom Cherry
777bac3299720623f4226bca103b26260052732ad30Tom Cherry    std::string seclabel = "";
778bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (command_arg > 2 && args[1] != "-") {
779bac3299720623f4226bca103b26260052732ad30Tom Cherry        seclabel = args[1];
780bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
781bac3299720623f4226bca103b26260052732ad30Tom Cherry    uid_t uid = 0;
782bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (command_arg > 3) {
783bac3299720623f4226bca103b26260052732ad30Tom Cherry        uid = decode_uid(args[2].c_str());
784bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
785bac3299720623f4226bca103b26260052732ad30Tom Cherry    gid_t gid = 0;
786bac3299720623f4226bca103b26260052732ad30Tom Cherry    std::vector<gid_t> supp_gids;
787bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (command_arg > 4) {
788bac3299720623f4226bca103b26260052732ad30Tom Cherry        gid = decode_uid(args[3].c_str());
789bac3299720623f4226bca103b26260052732ad30Tom Cherry        std::size_t nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */;
790bac3299720623f4226bca103b26260052732ad30Tom Cherry        for (size_t i = 0; i < nr_supp_gids; ++i) {
791bac3299720623f4226bca103b26260052732ad30Tom Cherry            supp_gids.push_back(decode_uid(args[4 + i].c_str()));
792bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
793bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
794bac3299720623f4226bca103b26260052732ad30Tom Cherry
795bac3299720623f4226bca103b26260052732ad30Tom Cherry    std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid,
7961b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes                                               supp_gids, namespace_flags,
7971b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes                                               seclabel, str_args));
798bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (!svc_p) {
799f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(ERROR) << "Couldn't allocate service for exec of '" << str_args[0] << "'";
800bac3299720623f4226bca103b26260052732ad30Tom Cherry        return nullptr;
801bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
802bac3299720623f4226bca103b26260052732ad30Tom Cherry    Service* svc = svc_p.get();
803bac3299720623f4226bca103b26260052732ad30Tom Cherry    services_.push_back(std::move(svc_p));
804bac3299720623f4226bca103b26260052732ad30Tom Cherry
805bac3299720623f4226bca103b26260052732ad30Tom Cherry    return svc;
806bac3299720623f4226bca103b26260052732ad30Tom Cherry}
807bac3299720623f4226bca103b26260052732ad30Tom Cherry
808bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByName(const std::string& name) const {
809bac3299720623f4226bca103b26260052732ad30Tom Cherry    auto svc = std::find_if(services_.begin(), services_.end(),
810bac3299720623f4226bca103b26260052732ad30Tom Cherry                            [&name] (const std::unique_ptr<Service>& s) {
811bac3299720623f4226bca103b26260052732ad30Tom Cherry                                return name == s->name();
812bac3299720623f4226bca103b26260052732ad30Tom Cherry                            });
813bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (svc != services_.end()) {
814bac3299720623f4226bca103b26260052732ad30Tom Cherry        return svc->get();
815bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
816bac3299720623f4226bca103b26260052732ad30Tom Cherry    return nullptr;
817bac3299720623f4226bca103b26260052732ad30Tom Cherry}
818bac3299720623f4226bca103b26260052732ad30Tom Cherry
819bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByPid(pid_t pid) const {
820bac3299720623f4226bca103b26260052732ad30Tom Cherry    auto svc = std::find_if(services_.begin(), services_.end(),
821bac3299720623f4226bca103b26260052732ad30Tom Cherry                            [&pid] (const std::unique_ptr<Service>& s) {
822bac3299720623f4226bca103b26260052732ad30Tom Cherry                                return s->pid() == pid;
823bac3299720623f4226bca103b26260052732ad30Tom Cherry                            });
824bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (svc != services_.end()) {
825bac3299720623f4226bca103b26260052732ad30Tom Cherry        return svc->get();
826bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
827bac3299720623f4226bca103b26260052732ad30Tom Cherry    return nullptr;
828bac3299720623f4226bca103b26260052732ad30Tom Cherry}
829bac3299720623f4226bca103b26260052732ad30Tom Cherry
830bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByKeychord(int keychord_id) const {
831bac3299720623f4226bca103b26260052732ad30Tom Cherry    auto svc = std::find_if(services_.begin(), services_.end(),
832bac3299720623f4226bca103b26260052732ad30Tom Cherry                            [&keychord_id] (const std::unique_ptr<Service>& s) {
833bac3299720623f4226bca103b26260052732ad30Tom Cherry                                return s->keychord_id() == keychord_id;
834bac3299720623f4226bca103b26260052732ad30Tom Cherry                            });
835bac3299720623f4226bca103b26260052732ad30Tom Cherry
836bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (svc != services_.end()) {
837bac3299720623f4226bca103b26260052732ad30Tom Cherry        return svc->get();
838bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
839bac3299720623f4226bca103b26260052732ad30Tom Cherry    return nullptr;
840bac3299720623f4226bca103b26260052732ad30Tom Cherry}
841bac3299720623f4226bca103b26260052732ad30Tom Cherry
842b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid ServiceManager::ForEachService(std::function<void(Service*)> callback) const {
843bac3299720623f4226bca103b26260052732ad30Tom Cherry    for (const auto& s : services_) {
844b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        callback(s.get());
845bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
846bac3299720623f4226bca103b26260052732ad30Tom Cherry}
847bac3299720623f4226bca103b26260052732ad30Tom Cherry
848bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachServiceInClass(const std::string& classname,
849bac3299720623f4226bca103b26260052732ad30Tom Cherry                                           void (*func)(Service* svc)) const {
850bac3299720623f4226bca103b26260052732ad30Tom Cherry    for (const auto& s : services_) {
851bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (classname == s->classname()) {
852bac3299720623f4226bca103b26260052732ad30Tom Cherry            func(s.get());
853bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
854bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
855bac3299720623f4226bca103b26260052732ad30Tom Cherry}
856bac3299720623f4226bca103b26260052732ad30Tom Cherry
857bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachServiceWithFlags(unsigned matchflags,
858bac3299720623f4226bca103b26260052732ad30Tom Cherry                                             void (*func)(Service* svc)) const {
859bac3299720623f4226bca103b26260052732ad30Tom Cherry    for (const auto& s : services_) {
860bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (s->flags() & matchflags) {
861bac3299720623f4226bca103b26260052732ad30Tom Cherry            func(s.get());
862bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
863bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
864bac3299720623f4226bca103b26260052732ad30Tom Cherry}
865bac3299720623f4226bca103b26260052732ad30Tom Cherry
866b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::RemoveService(const Service& svc) {
867bac3299720623f4226bca103b26260052732ad30Tom Cherry    auto svc_it = std::find_if(services_.begin(), services_.end(),
868bac3299720623f4226bca103b26260052732ad30Tom Cherry                               [&svc] (const std::unique_ptr<Service>& s) {
869bac3299720623f4226bca103b26260052732ad30Tom Cherry                                   return svc.name() == s->name();
870bac3299720623f4226bca103b26260052732ad30Tom Cherry                               });
871bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (svc_it == services_.end()) {
872bac3299720623f4226bca103b26260052732ad30Tom Cherry        return;
873bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
874bac3299720623f4226bca103b26260052732ad30Tom Cherry
875bac3299720623f4226bca103b26260052732ad30Tom Cherry    services_.erase(svc_it);
876bac3299720623f4226bca103b26260052732ad30Tom Cherry}
877bac3299720623f4226bca103b26260052732ad30Tom Cherry
878b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::DumpState() const {
879b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    for (const auto& s : services_) {
880b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        s->DumpState();
881b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
882b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
883b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
884b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETbool ServiceManager::ReapOneProcess() {
885b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    int status;
886b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
887b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    if (pid == 0) {
888b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        return false;
889b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    } else if (pid == -1) {
890f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        PLOG(ERROR) << "waitpid failed";
891b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        return false;
892b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    }
893b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
894b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    Service* svc = FindServiceByPid(pid);
895b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
896b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    std::string name;
897b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    if (svc) {
898b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        name = android::base::StringPrintf("Service '%s' (pid %d)",
899b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET                                           svc->name().c_str(), pid);
900b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    } else {
901b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        name = android::base::StringPrintf("Untracked pid %d", pid);
902b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    }
903b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
904b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    if (WIFEXITED(status)) {
905f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(VERBOSE) << name << " exited with status " << WEXITSTATUS(status);
906b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    } else if (WIFSIGNALED(status)) {
907f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(VERBOSE) << name << " killed by signal " << WTERMSIG(status);
908b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    } else if (WIFSTOPPED(status)) {
909f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(VERBOSE) << name << " stopped by signal " << WSTOPSIG(status);
910b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    } else {
911f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        LOG(VERBOSE) << name << " state changed";
912b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    }
913b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
914b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    if (!svc) {
915b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        return true;
916b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    }
917b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
918b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    if (svc->Reap()) {
919b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        waiting_for_exec = false;
920b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET        RemoveService(*svc);
921b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    }
922b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
923b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    return true;
924b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET}
925b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
926b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid ServiceManager::ReapAnyOutstandingChildren() {
927b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    while (ReapOneProcess()) {
928b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET    }
929b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET}
930b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET
931b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::ParseSection(const std::vector<std::string>& args,
932b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry                                 std::string* err) {
933b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (args.size() < 3) {
934b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        *err = "services must have a name and a program";
935b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        return false;
936b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
937b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
938b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    const std::string& name = args[1];
939b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (!IsValidName(name)) {
940b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        *err = StringPrintf("invalid service name '%s'", name.c_str());
941b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        return false;
942b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
943b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
944b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    std::vector<std::string> str_args(args.begin() + 2, args.end());
945b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    service_ = std::make_unique<Service>(name, "default", str_args);
946b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return true;
947b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
948b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
949b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
950b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry                                     const std::string& filename, int line,
951b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry                                     std::string* err) const {
952b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    return service_ ? service_->HandleLine(args, err) : false;
953b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
954b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
955b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceParser::EndSection() {
956b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    if (service_) {
957b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry        ServiceManager::GetInstance().AddService(std::move(service_));
958b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry    }
959b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}
960b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry
961b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::IsValidName(const std::string& name) const {
962bac3299720623f4226bca103b26260052732ad30Tom Cherry    if (name.size() > 16) {
963bac3299720623f4226bca103b26260052732ad30Tom Cherry        return false;
964bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
965bac3299720623f4226bca103b26260052732ad30Tom Cherry    for (const auto& c : name) {
966bac3299720623f4226bca103b26260052732ad30Tom Cherry        if (!isalnum(c) && (c != '_') && (c != '-')) {
967bac3299720623f4226bca103b26260052732ad30Tom Cherry            return false;
968bac3299720623f4226bca103b26260052732ad30Tom Cherry        }
969bac3299720623f4226bca103b26260052732ad30Tom Cherry    }
970bac3299720623f4226bca103b26260052732ad30Tom Cherry    return true;
971bac3299720623f4226bca103b26260052732ad30Tom Cherry}
972