Added a run_as string in json to configure which user the app has to be run by.

This commit is contained in:
unrealdragon 2026-10-08 13:29:57 +05:30
commit 7426d1dfd7
4 changed files with 38 additions and 5 deletions

View file

@ -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<std::shared_ptr<AppInfo>, 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;
}

View file

@ -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<std::string> 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<AppInfo> parent, State state);
bool isParentDependencyCleared(std::osyncstream &out) const;
std::string getModuleName() const;
std::string getProgramName() const;
std::string getRunAs() const;
std::deque<std::string> getArgs() const;
std::string getWorkingDir() const;
string_map getEnv() const;

View file

@ -8,6 +8,8 @@ extern "C" {
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pwd.h>
#include <grp.h>
#include <stdlib.h>
}
@ -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);
}

View file

@ -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<std::string>();
if(object.find("create_log") != object.end())
app_info.create_log = object["create_log"].get<bool>();
if(object.find("run_as") != object.end())
app_info.run_as = object["run_as"].get<std::string>();
app_info.env = env_list;
app_info.after = after_list;
app_info.module_name = object["name"].get<std::string>();
@ -514,6 +518,7 @@ int main(int argc, char *argv[]) {
initial_app_list.push_back(app_info);
}
std::vector<std::shared_ptr<AppInfo>> 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;