launch_daemon: Added run directive.
* Allows to conditionally (or unconditionally) launch targets. * Including tests for the settings parser. * FirstBootPrompt is now launched when deemed necessary (as in the Bootscript).
This commit is contained in:
+30
-6
@@ -1,9 +1,33 @@
|
|||||||
service x-vnd.Be-TRAK {
|
target desktop {
|
||||||
launch /system/Tracker
|
service x-vnd.Be-TRAK {
|
||||||
legacy
|
launch /system/Tracker
|
||||||
|
legacy
|
||||||
|
}
|
||||||
|
|
||||||
|
service x-vnd.Be-TSKB {
|
||||||
|
launch /system/Deskbar
|
||||||
|
legacy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
service x-vnd.Be-TSKB {
|
target first_boot {
|
||||||
launch /system/Deskbar
|
job x-vnd.Haiku-FirstBootPrompt {
|
||||||
legacy
|
launch /system/apps/FirstBootPrompt
|
||||||
|
legacy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run {
|
||||||
|
if {
|
||||||
|
or {
|
||||||
|
not file_exists /boot/home/config/settings/Locale\ settings
|
||||||
|
read_only
|
||||||
|
}
|
||||||
|
}
|
||||||
|
then {
|
||||||
|
first_boot
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
desktop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,9 @@ private:
|
|||||||
|
|
||||||
void _AddJobs(Target* target, BMessage& message);
|
void _AddJobs(Target* target, BMessage& message);
|
||||||
void _AddTargets(BMessage& message);
|
void _AddTargets(BMessage& message);
|
||||||
|
void _AddRunTargets(BMessage& message);
|
||||||
|
void _AddRunTargets(BMessage& message,
|
||||||
|
const char* name);
|
||||||
void _AddJob(Target* target, bool service,
|
void _AddJob(Target* target, bool service,
|
||||||
BMessage& message);
|
BMessage& message);
|
||||||
void _InitJobs();
|
void _InitJobs();
|
||||||
@@ -112,6 +115,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
JobMap fJobs;
|
JobMap fJobs;
|
||||||
TargetMap fTargets;
|
TargetMap fTargets;
|
||||||
|
BStringList fRunTargets;
|
||||||
JobQueue fJobQueue;
|
JobQueue fJobQueue;
|
||||||
SessionMap fSessions;
|
SessionMap fSessions;
|
||||||
MainWorker* fMainWorker;
|
MainWorker* fMainWorker;
|
||||||
@@ -237,6 +241,13 @@ LaunchDaemon::ReadyToRun()
|
|||||||
|
|
||||||
_InitJobs();
|
_InitJobs();
|
||||||
_LaunchJobs(NULL);
|
_LaunchJobs(NULL);
|
||||||
|
|
||||||
|
// Launch run targets
|
||||||
|
for (int32 index = 0; index < fRunTargets.CountStrings(); index++) {
|
||||||
|
Target* target = FindTarget(fRunTargets.StringAt(index));
|
||||||
|
if (target != NULL)
|
||||||
|
_LaunchJobs(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -457,6 +468,7 @@ LaunchDaemon::_ReadFile(const char* context, BEntry& entry)
|
|||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
_AddJobs(NULL, message);
|
_AddJobs(NULL, message);
|
||||||
_AddTargets(message);
|
_AddTargets(message);
|
||||||
|
_AddRunTargets(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -516,6 +528,50 @@ LaunchDaemon::_AddTargets(BMessage& message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchDaemon::_AddRunTargets(BMessage& message)
|
||||||
|
{
|
||||||
|
BMessage runMessage;
|
||||||
|
for (int32 index = 0; message.FindMessage("run", index,
|
||||||
|
&runMessage) == B_OK; index++) {
|
||||||
|
BMessage conditions;
|
||||||
|
bool pass = true;
|
||||||
|
if (runMessage.FindMessage("if", &conditions) == B_OK) {
|
||||||
|
Condition* condition = Conditions::FromMessage(conditions);
|
||||||
|
if (condition != NULL) {
|
||||||
|
pass = condition->Test(*this);
|
||||||
|
debug_printf("Test: %s -> %d\n", condition->ToString().String(),
|
||||||
|
pass);
|
||||||
|
delete condition;
|
||||||
|
} else
|
||||||
|
debug_printf("Could not parse condition!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pass) {
|
||||||
|
_AddRunTargets(runMessage, NULL);
|
||||||
|
_AddRunTargets(runMessage, "then");
|
||||||
|
} else {
|
||||||
|
_AddRunTargets(runMessage, "else");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchDaemon::_AddRunTargets(BMessage& message, const char* name)
|
||||||
|
{
|
||||||
|
BMessage targets;
|
||||||
|
if (name != NULL && message.FindMessage(name, &targets) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* target;
|
||||||
|
for (int32 index = 0; targets.FindString("target", index, &target) == B_OK;
|
||||||
|
index++) {
|
||||||
|
fRunTargets.Add(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message)
|
LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,6 +74,29 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RunConverter : public DriverSettingsConverter {
|
||||||
|
public:
|
||||||
|
status_t ConvertFromDriverSettings(const driver_parameter& parameter,
|
||||||
|
const char* name, int32 index, uint32 type, BMessage& target)
|
||||||
|
{
|
||||||
|
if (parameter.parameter_count == 0)
|
||||||
|
return target.AddString("target", parameter.values[index]);
|
||||||
|
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t ConvertEmptyFromDriverSettings(
|
||||||
|
const driver_parameter& parameter, const char* name, uint32 type,
|
||||||
|
BMessage& target)
|
||||||
|
{
|
||||||
|
if (parameter.parameter_count != 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return target.AddString("target", name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const static settings_template kConditionTemplate[] = {
|
const static settings_template kConditionTemplate[] = {
|
||||||
{B_STRING_TYPE, NULL, NULL, true, new ConditionConverter()},
|
{B_STRING_TYPE, NULL, NULL, true, new ConditionConverter()},
|
||||||
{B_MESSAGE_TYPE, "not", kConditionTemplate},
|
{B_MESSAGE_TYPE, "not", kConditionTemplate},
|
||||||
@@ -108,10 +131,24 @@ const static settings_template kTargetTemplate[] = {
|
|||||||
{0, NULL, NULL}
|
{0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const static settings_template kRunConditionalTemplate[] = {
|
||||||
|
{B_STRING_TYPE, NULL, NULL, true, new RunConverter()},
|
||||||
|
{0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
const static settings_template kRunTemplate[] = {
|
||||||
|
{B_STRING_TYPE, NULL, NULL, true, new RunConverter()},
|
||||||
|
{B_MESSAGE_TYPE, "if", kConditionTemplate},
|
||||||
|
{B_MESSAGE_TYPE, "then", kRunConditionalTemplate},
|
||||||
|
{B_MESSAGE_TYPE, "else", kRunConditionalTemplate},
|
||||||
|
{0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
const static settings_template kSettingsTemplate[] = {
|
const static settings_template kSettingsTemplate[] = {
|
||||||
{B_MESSAGE_TYPE, "target", kTargetTemplate},
|
{B_MESSAGE_TYPE, "target", kTargetTemplate},
|
||||||
{B_MESSAGE_TYPE, "job", kJobTemplate},
|
{B_MESSAGE_TYPE, "job", kJobTemplate},
|
||||||
{B_MESSAGE_TYPE, "service", kJobTemplate},
|
{B_MESSAGE_TYPE, "service", kJobTemplate},
|
||||||
|
{B_MESSAGE_TYPE, "run", kRunTemplate},
|
||||||
{0, NULL, NULL}
|
{0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ SettingsParserTest::TestConditionsMultiLineFlatNotWithArgs()
|
|||||||
BString(args.GetString("args", 0, "-")));
|
BString(args.GetString("args", 0, "-")));
|
||||||
CPPUNIT_ASSERT_EQUAL(BString("two"),
|
CPPUNIT_ASSERT_EQUAL(BString("two"),
|
||||||
BString(args.GetString("args", 1, "-")));
|
BString(args.GetString("args", 1, "-")));
|
||||||
CPPUNIT_ASSERT_EQUAL(2, args.CountNames(B_ANY_TYPE));
|
CPPUNIT_ASSERT_EQUAL(1, args.CountNames(B_ANY_TYPE));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(2, _ArrayCount(args, "args"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -177,11 +178,122 @@ SettingsParserTest::TestConditionsMultiLineNot()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsParserTest::TestRunFlat()
|
||||||
|
{
|
||||||
|
SettingsParser parser;
|
||||||
|
BMessage jobs;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, parser.Parse("run me", jobs));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, jobs.CountNames(B_ANY_TYPE));
|
||||||
|
|
||||||
|
BMessage message;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("run", &message));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("me"),
|
||||||
|
BString(message.GetString("target", "-")));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(message, "target"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsParserTest::TestRunMultiLine()
|
||||||
|
{
|
||||||
|
SettingsParser parser;
|
||||||
|
BMessage jobs;
|
||||||
|
status_t status = parser.Parse("run {\n"
|
||||||
|
"\tme\n"
|
||||||
|
"\tyou\n"
|
||||||
|
"}\n", jobs);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, status);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, jobs.CountNames(B_ANY_TYPE));
|
||||||
|
|
||||||
|
BMessage message;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("run", &message));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("me"),
|
||||||
|
BString(message.GetString("target", 0, "-")));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("you"),
|
||||||
|
BString(message.GetString("target", 1, "-")));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(2, _ArrayCount(message, "target"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsParserTest::TestRunIfThenElseFlat()
|
||||||
|
{
|
||||||
|
SettingsParser parser;
|
||||||
|
BMessage jobs;
|
||||||
|
status_t status = parser.Parse("run {\n"
|
||||||
|
"\tif safemode\n"
|
||||||
|
"\tthen this\n"
|
||||||
|
"\telse that\n"
|
||||||
|
"}\n", jobs);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, status);
|
||||||
|
|
||||||
|
BMessage message;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("run", &message));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(3, message.CountNames(B_ANY_TYPE));
|
||||||
|
|
||||||
|
BMessage then;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("then", &then));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("this"),
|
||||||
|
BString(then.GetString("target", "-")));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(then, "target"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, then.CountNames(B_ANY_TYPE));
|
||||||
|
|
||||||
|
BMessage otherwise;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("else", &otherwise));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("that"),
|
||||||
|
BString(otherwise.GetString("target", "-")));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(otherwise, "target"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, otherwise.CountNames(B_ANY_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsParserTest::TestRunIfThenElseMultiLine()
|
||||||
|
{
|
||||||
|
SettingsParser parser;
|
||||||
|
BMessage jobs;
|
||||||
|
status_t status = parser.Parse("run {\n"
|
||||||
|
"\tif {\n"
|
||||||
|
"\t\tread_only\n"
|
||||||
|
"\t}\n"
|
||||||
|
"\tthen {\n"
|
||||||
|
"\t\tthis\n"
|
||||||
|
"\t}\n"
|
||||||
|
"\telse {\n"
|
||||||
|
"\t\tthat\n"
|
||||||
|
"\t}\n"
|
||||||
|
"}\n", jobs);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, status);
|
||||||
|
|
||||||
|
BMessage message;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("run", &message));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(3, message.CountNames(B_ANY_TYPE));
|
||||||
|
|
||||||
|
BMessage then;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("then", &then));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("this"),
|
||||||
|
BString(then.GetString("target", "-")));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(then, "target"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, then.CountNames(B_ANY_TYPE));
|
||||||
|
|
||||||
|
BMessage otherwise;
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("else", &otherwise));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("that"),
|
||||||
|
BString(otherwise.GetString("target", "-")));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(otherwise, "target"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, otherwise.CountNames(B_ANY_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
SettingsParserTest::AddTests(BTestSuite& parent)
|
SettingsParserTest::AddTests(BTestSuite& parent)
|
||||||
{
|
{
|
||||||
CppUnit::TestSuite& suite = *new CppUnit::TestSuite("SettingsParserTest");
|
CppUnit::TestSuite& suite = *new CppUnit::TestSuite("SettingsParserTest");
|
||||||
|
|
||||||
|
// Conditions
|
||||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||||
"SettingsParserTest::TestConditionsMultiLine",
|
"SettingsParserTest::TestConditionsMultiLine",
|
||||||
&SettingsParserTest::TestConditionsMultiLine));
|
&SettingsParserTest::TestConditionsMultiLine));
|
||||||
@@ -207,6 +319,20 @@ SettingsParserTest::AddTests(BTestSuite& parent)
|
|||||||
"SettingsParserTest::TestConditionsMultiLineNot",
|
"SettingsParserTest::TestConditionsMultiLineNot",
|
||||||
&SettingsParserTest::TestConditionsMultiLineNot));
|
&SettingsParserTest::TestConditionsMultiLineNot));
|
||||||
|
|
||||||
|
// Run
|
||||||
|
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||||
|
"SettingsParserTest::TestRunFlat",
|
||||||
|
&SettingsParserTest::TestRunFlat));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||||
|
"SettingsParserTest::TestRunMultiLine",
|
||||||
|
&SettingsParserTest::TestRunMultiLine));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||||
|
"SettingsParserTest::TestRunIfThenElseFlat",
|
||||||
|
&SettingsParserTest::TestRunIfThenElseFlat));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||||
|
"SettingsParserTest::TestRunIfThenElseMultiLine",
|
||||||
|
&SettingsParserTest::TestRunIfThenElseMultiLine));
|
||||||
|
|
||||||
parent.addTest("SettingsParserTest", &suite);
|
parent.addTest("SettingsParserTest", &suite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,3 +359,14 @@ SettingsParserTest::_ParseCondition(const char* text, BMessage& message)
|
|||||||
|
|
||||||
return job.FindMessage("if", &message);
|
return job.FindMessage("if", &message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
SettingsParserTest::_ArrayCount(BMessage& message, const char* name)
|
||||||
|
{
|
||||||
|
int32 found;
|
||||||
|
if (message.GetInfo(name, NULL, &found, NULL) != B_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,11 +26,18 @@ public:
|
|||||||
void TestConditionsMultiLineFlatNotWithArgs();
|
void TestConditionsMultiLineFlatNotWithArgs();
|
||||||
void TestConditionsMultiLineNot();
|
void TestConditionsMultiLineNot();
|
||||||
|
|
||||||
|
void TestRunFlat();
|
||||||
|
void TestRunMultiLine();
|
||||||
|
void TestRunIfThenElseFlat();
|
||||||
|
void TestRunIfThenElseMultiLine();
|
||||||
|
|
||||||
static void AddTests(BTestSuite& suite);
|
static void AddTests(BTestSuite& suite);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _ParseCondition(const char* text,
|
status_t _ParseCondition(const char* text,
|
||||||
BMessage& message);
|
BMessage& message);
|
||||||
|
int32 _ArrayCount(BMessage& message,
|
||||||
|
const char* name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user