launch_daemon: Now supports getting the env from a script.
* Scripts from targets are evaluated once on first target launch, scripts from jobs are evaluated on each start. * The "desktop" target now sources SetupEnvironment as usual.
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
target desktop {
|
target desktop {
|
||||||
|
env /system/boot/SetupEnvironment
|
||||||
|
|
||||||
service x-vnd.Be-TRAK {
|
service x-vnd.Be-TRAK {
|
||||||
launch /system/Tracker
|
launch /system/Tracker
|
||||||
legacy
|
legacy
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#include "BaseJob.h"
|
#include "BaseJob.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
|
|
||||||
#include "Conditions.h"
|
#include "Conditions.h"
|
||||||
@@ -70,6 +73,13 @@ BaseJob::Environment() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStringList&
|
||||||
|
BaseJob::Environment()
|
||||||
|
{
|
||||||
|
return fEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const BStringList&
|
const BStringList&
|
||||||
BaseJob::EnvironmentSourceFiles() const
|
BaseJob::EnvironmentSourceFiles() const
|
||||||
{
|
{
|
||||||
@@ -77,6 +87,13 @@ BaseJob::EnvironmentSourceFiles() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStringList&
|
||||||
|
BaseJob::EnvironmentSourceFiles()
|
||||||
|
{
|
||||||
|
return fSourceFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseJob::SetEnvironment(const BMessage& message)
|
BaseJob::SetEnvironment(const BMessage& message)
|
||||||
{
|
{
|
||||||
@@ -85,7 +102,7 @@ BaseJob::SetEnvironment(const BMessage& message)
|
|||||||
int32 count;
|
int32 count;
|
||||||
for (int32 index = 0; message.GetInfo(B_STRING_TYPE, index, &name, &type,
|
for (int32 index = 0; message.GetInfo(B_STRING_TYPE, index, &name, &type,
|
||||||
&count) == B_OK; index++) {
|
&count) == B_OK; index++) {
|
||||||
if (strcmp(name, "from_file") == 0) {
|
if (strcmp(name, "from_script") == 0) {
|
||||||
const char* fromFile;
|
const char* fromFile;
|
||||||
for (int32 fileIndex = 0; message.FindString(name, fileIndex,
|
for (int32 fileIndex = 0; message.FindString(name, fileIndex,
|
||||||
&fromFile) == B_OK; fileIndex++) {
|
&fromFile) == B_OK; fileIndex++) {
|
||||||
@@ -109,3 +126,113 @@ BaseJob::SetEnvironment(const BMessage& message)
|
|||||||
fEnvironment.Add(variable);
|
fEnvironment.Add(variable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseJob::GetSourceFilesEnvironment(BStringList& environment)
|
||||||
|
{
|
||||||
|
int32 count = fSourceFiles.CountStrings();
|
||||||
|
for (int32 index = 0; index < count; index++) {
|
||||||
|
_GetSourceFileEnvironment(fSourceFiles.StringAt(index), fEnvironment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Gets the environment by evaluating the source files, and move that
|
||||||
|
environment to the static environment.
|
||||||
|
|
||||||
|
When this method returns, the source files list will be empty.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
BaseJob::ResolveSourceFiles()
|
||||||
|
{
|
||||||
|
if (fSourceFiles.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
GetSourceFilesEnvironment(fEnvironment);
|
||||||
|
fSourceFiles.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseJob::_GetSourceFileEnvironment(const char* script, BStringList& environment)
|
||||||
|
{
|
||||||
|
int pipes[2];
|
||||||
|
if (pipe(&pipes[0]) != 0) {
|
||||||
|
// TODO: log error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t child = fork();
|
||||||
|
if (child < 0) {
|
||||||
|
// TODO: log error
|
||||||
|
} else if (child == 0) {
|
||||||
|
// We're the child, redirect stdout
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
close(STDERR_FILENO);
|
||||||
|
dup2(pipes[1], STDOUT_FILENO);
|
||||||
|
dup2(pipes[1], STDERR_FILENO);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < 2; i++)
|
||||||
|
close(pipes[i]);
|
||||||
|
|
||||||
|
BString command;
|
||||||
|
command.SetToFormat(". \"%s\"; export -p", script);
|
||||||
|
execl("/bin/sh", "/bin/sh", "-c", command.String(), NULL);
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
// Retrieve environment from child
|
||||||
|
|
||||||
|
close(pipes[1]);
|
||||||
|
|
||||||
|
BString line;
|
||||||
|
char buffer[4096];
|
||||||
|
while (true) {
|
||||||
|
ssize_t bytesRead = read(pipes[0], buffer, sizeof(buffer) - 1);
|
||||||
|
if (bytesRead <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Make sure the buffer is null terminated
|
||||||
|
buffer[bytesRead] = 0;
|
||||||
|
|
||||||
|
const char* chunk = buffer;
|
||||||
|
while (true) {
|
||||||
|
const char* separator = strchr(chunk, '\n');
|
||||||
|
if (separator == NULL) {
|
||||||
|
line.Append(chunk, bytesRead);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line.Append(chunk, separator - chunk);
|
||||||
|
chunk = separator + 1;
|
||||||
|
|
||||||
|
_ParseExportVariable(environment, line);
|
||||||
|
line.Truncate(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!line.IsEmpty())
|
||||||
|
_ParseExportVariable(environment, line);
|
||||||
|
|
||||||
|
close(pipes[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseJob::_ParseExportVariable(BStringList& environment, const BString& line)
|
||||||
|
{
|
||||||
|
if (!line.StartsWith("export "))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int separator = line.FindFirst("=\"");
|
||||||
|
if (separator < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BString variable;
|
||||||
|
line.CopyInto(variable, 7, separator - 7);
|
||||||
|
|
||||||
|
BString value;
|
||||||
|
line.CopyInto(value, separator + 2, line.Length() - separator - 3);
|
||||||
|
|
||||||
|
variable << "=" << value;
|
||||||
|
environment.Add(variable);
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,9 +30,21 @@ public:
|
|||||||
bool CheckCondition(ConditionContext& context) const;
|
bool CheckCondition(ConditionContext& context) const;
|
||||||
|
|
||||||
const BStringList& Environment() const;
|
const BStringList& Environment() const;
|
||||||
|
BStringList& Environment();
|
||||||
const BStringList& EnvironmentSourceFiles() const;
|
const BStringList& EnvironmentSourceFiles() const;
|
||||||
|
BStringList& EnvironmentSourceFiles();
|
||||||
void SetEnvironment(const BMessage& message);
|
void SetEnvironment(const BMessage& message);
|
||||||
|
|
||||||
|
void GetSourceFilesEnvironment(
|
||||||
|
BStringList& environment);
|
||||||
|
void ResolveSourceFiles();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _GetSourceFileEnvironment(const char* script,
|
||||||
|
BStringList& environment);
|
||||||
|
void _ParseExportVariable(BStringList& environment,
|
||||||
|
const BString& line);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
::Condition* fCondition;
|
::Condition* fCondition;
|
||||||
BStringList fEnvironment;
|
BStringList fEnvironment;
|
||||||
|
|||||||
@@ -306,7 +306,6 @@ Job::Launch()
|
|||||||
{
|
{
|
||||||
// Build environment
|
// Build environment
|
||||||
|
|
||||||
// TODO: resolve environment source files
|
|
||||||
std::vector<const char*> environment;
|
std::vector<const char*> environment;
|
||||||
for (const char** variable = (const char**)environ; variable[0] != NULL;
|
for (const char** variable = (const char**)environ; variable[0] != NULL;
|
||||||
variable++) {
|
variable++) {
|
||||||
@@ -317,6 +316,11 @@ Job::Launch()
|
|||||||
_AddStringList(environment, Target()->Environment());
|
_AddStringList(environment, Target()->Environment());
|
||||||
_AddStringList(environment, Environment());
|
_AddStringList(environment, Environment());
|
||||||
|
|
||||||
|
// Resolve source files
|
||||||
|
BStringList sourceFilesEnvironment;
|
||||||
|
GetSourceFilesEnvironment(sourceFilesEnvironment);
|
||||||
|
_AddStringList(environment, sourceFilesEnvironment);
|
||||||
|
|
||||||
environment.push_back(NULL);
|
environment.push_back(NULL);
|
||||||
|
|
||||||
if (fArguments.IsEmpty()) {
|
if (fArguments.IsEmpty()) {
|
||||||
|
|||||||
@@ -684,6 +684,9 @@ LaunchDaemon::_LaunchJobs(Target* target)
|
|||||||
void
|
void
|
||||||
LaunchDaemon::_AddLaunchJob(Job* job)
|
LaunchDaemon::_AddLaunchJob(Job* job)
|
||||||
{
|
{
|
||||||
|
if (job->Target() != NULL)
|
||||||
|
job->Target()->ResolveSourceFiles();
|
||||||
|
|
||||||
if (!job->IsLaunched() && job->CheckCondition(*this))
|
if (!job->IsLaunched() && job->CheckCondition(*this))
|
||||||
fJobQueue.AddJob(job);
|
fJobQueue.AddJob(job);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ const static settings_template kPortTemplate[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const static settings_template kEnvTemplate[] = {
|
const static settings_template kEnvTemplate[] = {
|
||||||
{B_STRING_TYPE, "from_file", NULL, true},
|
{B_STRING_TYPE, "from_script", NULL, true},
|
||||||
{B_STRING_TYPE, NULL, NULL},
|
{B_STRING_TYPE, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user