blob: 127bf41a51064d20bae40b9c650f5ff4cece3e29 [file] [log] [blame]
#include <pwd.h>
#include <unistd.h>
#include <ostream>
#include <string>
#include "absl/flags/flag.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "aos/configuration.h"
#include "aos/events/event_loop.h"
#include "aos/flatbuffers.h"
#include "aos/init.h"
#include "aos/starter/starterd_lib.h"
#include "aos/util/file.h"
ABSL_FLAG(std::string, config, "aos_config.json",
"File path of aos configuration");
ABSL_FLAG(std::string, user, "",
"Starter runs as though this user ran a SUID binary if set.");
ABSL_FLAG(std::string, version_string, "",
"Version to report for starterd and subprocesses.");
ABSL_DECLARE_FLAG(std::string, shm_base);
ABSL_FLAG(bool, purge_shm_base, false,
"If true, delete everything in --shm_base before starting.");
int main(int argc, char **argv) {
aos::InitGoogle(&argc, &argv);
if (absl::GetFlag(FLAGS_purge_shm_base)) {
aos::util::UnlinkRecursive(absl::GetFlag(FLAGS_shm_base));
}
if (!absl::GetFlag(FLAGS_user).empty()) {
uid_t uid;
uid_t gid;
{
struct passwd *user_data = getpwnam(absl::GetFlag(FLAGS_user).c_str());
if (user_data != nullptr) {
uid = user_data->pw_uid;
gid = user_data->pw_gid;
} else {
LOG(FATAL) << "Could not find user " << absl::GetFlag(FLAGS_user);
return 1;
}
}
// Change the real and effective IDs to the user we're running as. The
// effective IDs mean files we access (like shared memory) will happen as
// that user. The real IDs allow child processes with an different effective
// ID to still participate in signal sending/receiving.
constexpr int kUnchanged = -1;
if (setresgid(/* ruid */ gid, /* euid */ gid,
/* suid */ kUnchanged) != 0) {
PLOG(FATAL) << "Failed to change GID to " << absl::GetFlag(FLAGS_user)
<< ", group " << gid;
}
if (setresuid(/* ruid */ uid, /* euid */ uid,
/* suid */ kUnchanged) != 0) {
PLOG(FATAL) << "Failed to change UID to " << absl::GetFlag(FLAGS_user);
}
}
aos::FlatbufferDetachedBuffer<aos::Configuration> config =
aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
const aos::Configuration *config_msg = &config.message();
aos::starter::Starter starter(config_msg);
if (!absl::GetFlag(FLAGS_version_string).empty()) {
starter.event_loop()->SetVersionString(absl::GetFlag(FLAGS_version_string));
}
starter.Run();
return 0;
}