From ea19a80ed6ba3f34abb2e4d138ddc666580b8d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 6 Jul 2015 21:20:18 +0200 Subject: [PATCH] launch_daemon: Added support for setting env. * We cannot "source" files through a shell yet, though. --- src/servers/launch/BaseJob.cpp | 50 +++++++++++++++++++++++++++ src/servers/launch/BaseJob.h | 8 +++++ src/servers/launch/Job.cpp | 50 ++++++++++++++++++++++----- src/servers/launch/Job.h | 3 ++ src/servers/launch/LaunchDaemon.cpp | 14 +++++++- src/servers/launch/SettingsParser.cpp | 7 ++++ 6 files changed, 123 insertions(+), 9 deletions(-) diff --git a/src/servers/launch/BaseJob.cpp b/src/servers/launch/BaseJob.cpp index cdf62adf4e..e1c3ffc00a 100644 --- a/src/servers/launch/BaseJob.cpp +++ b/src/servers/launch/BaseJob.cpp @@ -6,6 +6,8 @@ #include "BaseJob.h" +#include + #include "Conditions.h" @@ -59,3 +61,51 @@ BaseJob::CheckCondition(ConditionContext& context) const return true; } + + +const BStringList& +BaseJob::Environment() const +{ + return fEnvironment; +} + + +const BStringList& +BaseJob::EnvironmentSourceFiles() const +{ + return fSourceFiles; +} + + +void +BaseJob::SetEnvironment(const BMessage& message) +{ + char* name; + type_code type; + int32 count; + for (int32 index = 0; message.GetInfo(B_STRING_TYPE, index, &name, &type, + &count) == B_OK; index++) { + if (strcmp(name, "from_file") == 0) { + const char* fromFile; + for (int32 fileIndex = 0; message.FindString(name, fileIndex, + &fromFile) == B_OK; fileIndex++) { + fSourceFiles.Add(fromFile); + } + continue; + } + + BString variable = name; + variable << "='"; + + const char* argument; + for (int32 argumentIndex = 0; message.FindString(name, argumentIndex, + &argument) == B_OK; argumentIndex++) { + if (argumentIndex > 0) + variable << " "; + variable += argument; + } + variable << "'"; + + fEnvironment.Add(variable); + } +} diff --git a/src/servers/launch/BaseJob.h b/src/servers/launch/BaseJob.h index 5fa1afc332..4c014f3373 100644 --- a/src/servers/launch/BaseJob.h +++ b/src/servers/launch/BaseJob.h @@ -7,10 +7,12 @@ #include +#include using namespace BSupportKit; +class BMessage; class Condition; class ConditionContext; @@ -27,8 +29,14 @@ public: void SetCondition(::Condition* condition); bool CheckCondition(ConditionContext& context) const; + const BStringList& Environment() const; + const BStringList& EnvironmentSourceFiles() const; + void SetEnvironment(const BMessage& message); + protected: ::Condition* fCondition; + BStringList fEnvironment; + BStringList fSourceFiles; }; diff --git a/src/servers/launch/Job.cpp b/src/servers/launch/Job.cpp index 449ae0c34c..9e7606271c 100644 --- a/src/servers/launch/Job.cpp +++ b/src/servers/launch/Job.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include "Target.h" @@ -303,26 +304,49 @@ Job::Port(const char* name) const status_t Job::Launch() { + // Build environment + + // TODO: resolve environment source files + std::vector environment; + for (const char** variable = (const char**)environ; variable[0] != NULL; + variable++) { + environment.push_back(variable[0]); + } + + if (Target() != NULL) + _AddStringList(environment, Target()->Environment()); + _AddStringList(environment, Environment()); + + environment.push_back(NULL); + if (fArguments.IsEmpty()) { // Launch by signature BString signature("application/"); signature << Name(); - return be_roster->Launch(signature.String(), (BMessage*)NULL, &fTeam); + return BRoster::Private().Launch(signature.String(), NULL, NULL, + 0, NULL, environment.begin(), &fTeam); } + // Build argument vector + entry_ref ref; status_t status = get_ref_for_path(fArguments.StringAt(0).String(), &ref); if (status != B_OK) return status; - size_t count = fArguments.CountStrings() - 1; - const char* args[count + 1]; - for (int32 i = 1; i < fArguments.CountStrings(); i++) { - args[i - 1] = fArguments.StringAt(i); - } - args[count] = NULL; + std::vector args; - return be_roster->Launch(&ref, count, args, &fTeam); + size_t count = fArguments.CountStrings() - 1; + if (count > 0) { + for (int32 i = 1; i < fArguments.CountStrings(); i++) { + args.push_back(fArguments.StringAt(i)); + } + args.push_back(NULL); + } + + // Launch via entry_ref + return BRoster::Private().Launch(NULL, &ref, NULL, count, args.begin(), + environment.begin(), &fTeam); } @@ -380,3 +404,13 @@ Job::_AddRequirement(BJob* dependency) return B_OK; } + + +void +Job::_AddStringList(std::vector& array, const BStringList& list) +{ + int32 count = list.CountStrings(); + for (int32 index = 0; index < count; index++) { + array.push_back(list.StringAt(index).String()); + } +} diff --git a/src/servers/launch/Job.h b/src/servers/launch/Job.h index 3b868b499b..0adc504a3d 100644 --- a/src/servers/launch/Job.h +++ b/src/servers/launch/Job.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -72,6 +73,8 @@ private: Job& operator=(const Job& other); void _DeletePorts(); status_t _AddRequirement(BJob* dependency); + void _AddStringList(std::vector& array, + const BStringList& list); private: BStringList fArguments; diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index 5caef5c05a..084ecbf760 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -104,6 +104,8 @@ private: void _AddTarget(Target* target); void _SetCondition(BaseJob* job, const BMessage& message); + void _SetEnvironment(BaseJob* job, + const BMessage& message); status_t _StartSession(const char* login); @@ -523,6 +525,7 @@ LaunchDaemon::_AddTargets(BMessage& message) } _SetCondition(target, targetMessage); + _SetEnvironment(target, targetMessage); _AddJobs(target, targetMessage); } } @@ -600,7 +603,7 @@ LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message) job->SetCreateDefaultPort(!message.GetBool("legacy", !service)); _SetCondition(job, message); - + _SetEnvironment(job, message); BMessage portMessage; for (int32 index = 0; @@ -715,6 +718,15 @@ LaunchDaemon::_SetCondition(BaseJob* job, const BMessage& message) } +void +LaunchDaemon::_SetEnvironment(BaseJob* job, const BMessage& message) +{ + BMessage environmentMessage; + if (message.FindMessage("env", &environmentMessage) == B_OK) + job->SetEnvironment(environmentMessage); +} + + status_t LaunchDaemon::_StartSession(const char* login) { diff --git a/src/servers/launch/SettingsParser.cpp b/src/servers/launch/SettingsParser.cpp index 3606de0ff5..1da79e881b 100644 --- a/src/servers/launch/SettingsParser.cpp +++ b/src/servers/launch/SettingsParser.cpp @@ -110,6 +110,11 @@ const static settings_template kPortTemplate[] = { {B_INT32_TYPE, "capacity", NULL}, }; +const static settings_template kEnvTemplate[] = { + {B_STRING_TYPE, "from_file", NULL, true}, + {B_STRING_TYPE, NULL, NULL}, +}; + const static settings_template kJobTemplate[] = { {B_STRING_TYPE, "name", NULL, true}, {B_BOOL_TYPE, "disabled", NULL}, @@ -119,6 +124,7 @@ const static settings_template kJobTemplate[] = { {B_MESSAGE_TYPE, "port", kPortTemplate}, {B_MESSAGE_TYPE, "if", kConditionTemplate}, {B_BOOL_TYPE, "no_safemode", NULL}, + {B_MESSAGE_TYPE, "env", kEnvTemplate}, {0, NULL, NULL} }; @@ -127,6 +133,7 @@ const static settings_template kTargetTemplate[] = { {B_BOOL_TYPE, "reset", NULL}, {B_MESSAGE_TYPE, "if", kConditionTemplate}, {B_BOOL_TYPE, "no_safemode", NULL}, + {B_MESSAGE_TYPE, "env", kEnvTemplate}, {B_MESSAGE_TYPE, "job", kJobTemplate}, {B_MESSAGE_TYPE, "service", kJobTemplate}, {0, NULL, NULL}