diff --git a/appinfo.cpp b/appinfo.cpp index f71221b..8e25163 100644 --- a/appinfo.cpp +++ b/appinfo.cpp @@ -52,6 +52,11 @@ void AppInfo::setRunMode(std::string mode) } } +void AppInfo::setRunAs(std::string run_as) +{ + this->run_as = run_as; +} + void AppInfo::setFinished() { this->state = State::exited; @@ -89,6 +94,11 @@ std::string AppInfo::getProgramName() const return program_name; } +std::string AppInfo::getRunAs() const +{ + return run_as; +} + std::string AppInfo::getWorkingDir() const { return working_dir; @@ -143,6 +153,7 @@ void AppInfo::copyFromData(AppInfo::AppData &other) this->after = other.after; this->env = other.env; setRunMode(other.run_mode); + setRunAs(other.run_as); } std::unordered_map, AppInfo::State> AppInfo::getParents() const @@ -232,6 +243,7 @@ void AppInfo::printInfo(std::ostream &out) env = env.substr(0,env.size() - 2); out << "Environment: " << env << std::endl; out << "Create Log: " << create_log << std::endl; + out << "Run as: " << run_as << std::endl; out << "************************************End************************************" << std::endl; } @@ -296,6 +308,7 @@ void AppInfo::AppData::printInfo(std::ostream &out) env = env.substr(0,env.size() - 2); out << "Environment: " << env << std::endl; out << "Create Log: " << AppData::create_log << std::endl; + out << "Run as: " << run_as << std::endl; out << "************************************End************************************" << std::endl; } diff --git a/appinfo.h b/appinfo.h index 6fc4c80..040b3d8 100644 --- a/appinfo.h +++ b/appinfo.h @@ -30,6 +30,7 @@ public: string_map after; string_map env; std::string run_mode; + std::string run_as; bool create_log = false; void printInfo(std::ostream &out); std::string getAfterString() const; @@ -40,6 +41,7 @@ private: std::string program_name; std::string module_name; std::deque args; + std::string run_as; std::string working_dir; string_map after; string_map env; @@ -56,12 +58,14 @@ public: void setEnv(string_map env); void setCreateLog(bool create_log); void setRunMode(std::string mode); + void setRunAs(std::string run_as); void setFinished(); void setRunning(); void insertParent(std::shared_ptr parent, State state); bool isParentDependencyCleared(std::osyncstream &out) const; std::string getModuleName() const; std::string getProgramName() const; + std::string getRunAs() const; std::deque getArgs() const; std::string getWorkingDir() const; string_map getEnv() const; diff --git a/executionmanager.cpp b/executionmanager.cpp index 91ad5ac..2f6889f 100644 --- a/executionmanager.cpp +++ b/executionmanager.cpp @@ -8,6 +8,8 @@ extern "C" { #include #include #include +#include +#include #include } @@ -96,6 +98,10 @@ void ExecutionManager::run() std::string program_name = ptr->getProgramName(); std::string program_log_name_temp = module_name + ".log"; std::string program_log_name = ""; + std::string run_as = ptr->getRunAs(); + struct passwd *pw = nullptr; + if(run_as.size() != 0) + pw = getpwnam(run_as.c_str()); for(auto &ch: program_log_name_temp) { if(ch != ' ') { program_log_name += ch; @@ -127,6 +133,11 @@ void ExecutionManager::run() if(!dir.empty()) { int err = chdir(dir.c_str()); } + if(pw) { + initgroups(pw->pw_name, pw->pw_gid); + setgid(pw->pw_gid); + setuid(pw->pw_uid); + } for(auto &[key,value]: env) { setenv(key.data(), value.data(), 1); } diff --git a/main.cpp b/main.cpp index c751b7b..e9080e9 100644 --- a/main.cpp +++ b/main.cpp @@ -108,18 +108,19 @@ void printJsonHelp() { std::cout << "\t[REQUIRED] run_mode[string] : Mode can be daemon or script." << std::endl; std::cout << "\t\tMode daemon : The app forks the program and exits without waiting." << std::endl; std::cout << "\t\tMode script : The app forks the program and waits for it to finish execution." << std::endl; - std::cout << "\t\tMode script : If no run_mode is given it is presumed to be script." << std::endl; + std::cout << "\t\t If no run_mode is given it is presumed to be script." << std::endl; std::cout << "\t[OPTIONAL] after[{name,state}] : List containing names and state of modules." << std::endl; std::cout << "\t\tname[string] : Name of the other module." << std::endl; std::cout << "\t\tstate[string]: State of the other module." << std::endl; - std::cout << "\t\t\t\tState exited : Specified module must have finished execution." << std::endl; - std::cout << "\t\t\t\tState running : Specified module must be running." << std::endl; + std::cout << "\t\t\tState exited : Specified module must have finished execution." << std::endl; + std::cout << "\t\t\tState running : Specified module must be running." << std::endl; std::cout << "\t\tThis module will be launched after the module found\n\t\t" "in this list using name is at the state specified as state." << std::endl; std::cout << "\t[OPTIONAL] env{} : Additional enviroment variables." << std::endl; std::cout << "\t\tEvery key in this object will be used as environment name,\n\t\tand every corresponding value as its value." << std::endl; std::cout << "\t[OPTIONAL] working_dir[string] : Working directory of the program." << std::endl; std::cout << "\t[OPTIONAL] create_log[boolean] : Create a log file at logs path." << std::endl; + std::cout << "\t[OPTIONAL] run_as[string] : Run as a particular user." << std::endl; std::cout << std::endl << "Example startup_apps.json: "; std::cout << R"( [ @@ -138,8 +139,9 @@ void printJsonHelp() { "run_mode": "script", "create_log": true, "after": [{"module": "LS 0", "state": "exited"}], - "env": {"PATH": "/home/:/usr/bin/", "NAME": "ONE"} - "working_dir": "/home/etc" + "env": {"PATH": "/home/:/usr/bin/", "NAME": "ONE"}, + "working_dir": "/home/etc", + "run_as": "username" } ] )" << std::endl; @@ -506,6 +508,8 @@ int main(int argc, char *argv[]) { app_info.working_dir = object["working_dir"].get(); if(object.find("create_log") != object.end()) app_info.create_log = object["create_log"].get(); + if(object.find("run_as") != object.end()) + app_info.run_as = object["run_as"].get(); app_info.env = env_list; app_info.after = after_list; app_info.module_name = object["name"].get(); @@ -514,6 +518,7 @@ int main(int argc, char *argv[]) { initial_app_list.push_back(app_info); } std::vector> list; + log_file << "Checking App List for errors." << std::endl; auto list_check = checkAppList(initial_app_list, list, log_file.rdbuf()); if(list_check.has_value()) { log_file << "No errors found in app list." << std::endl;