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:
parent
d91addd24c
commit
004cd6709d
@ -1,9 +1,33 @@
|
||||
service x-vnd.Be-TRAK {
|
||||
launch /system/Tracker
|
||||
legacy
|
||||
target desktop {
|
||||
service x-vnd.Be-TRAK {
|
||||
launch /system/Tracker
|
||||
legacy
|
||||
}
|
||||
|
||||
service x-vnd.Be-TSKB {
|
||||
launch /system/Deskbar
|
||||
legacy
|
||||
}
|
||||
}
|
||||
|
||||
service x-vnd.Be-TSKB {
|
||||
launch /system/Deskbar
|
||||
legacy
|
||||
target first_boot {
|
||||
job x-vnd.Haiku-FirstBootPrompt {
|
||||
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 _AddTargets(BMessage& message);
|
||||
void _AddRunTargets(BMessage& message);
|
||||
void _AddRunTargets(BMessage& message,
|
||||
const char* name);
|
||||
void _AddJob(Target* target, bool service,
|
||||
BMessage& message);
|
||||
void _InitJobs();
|
||||
@ -112,6 +115,7 @@ private:
|
||||
private:
|
||||
JobMap fJobs;
|
||||
TargetMap fTargets;
|
||||
BStringList fRunTargets;
|
||||
JobQueue fJobQueue;
|
||||
SessionMap fSessions;
|
||||
MainWorker* fMainWorker;
|
||||
@ -237,6 +241,13 @@ LaunchDaemon::ReadyToRun()
|
||||
|
||||
_InitJobs();
|
||||
_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) {
|
||||
_AddJobs(NULL, message);
|
||||
_AddTargets(message);
|
||||
_AddRunTargets(message);
|
||||
}
|
||||
|
||||
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
|
||||
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[] = {
|
||||
{B_STRING_TYPE, NULL, NULL, true, new ConditionConverter()},
|
||||
{B_MESSAGE_TYPE, "not", kConditionTemplate},
|
||||
@ -108,10 +131,24 @@ const static settings_template kTargetTemplate[] = {
|
||||
{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[] = {
|
||||
{B_MESSAGE_TYPE, "target", kTargetTemplate},
|
||||
{B_MESSAGE_TYPE, "job", kJobTemplate},
|
||||
{B_MESSAGE_TYPE, "service", kJobTemplate},
|
||||
{B_MESSAGE_TYPE, "run", kRunTemplate},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -153,7 +153,8 @@ SettingsParserTest::TestConditionsMultiLineFlatNotWithArgs()
|
||||
BString(args.GetString("args", 0, "-")));
|
||||
CPPUNIT_ASSERT_EQUAL(BString("two"),
|
||||
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
|
||||
SettingsParserTest::AddTests(BTestSuite& parent)
|
||||
{
|
||||
CppUnit::TestSuite& suite = *new CppUnit::TestSuite("SettingsParserTest");
|
||||
|
||||
// Conditions
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsMultiLine",
|
||||
&SettingsParserTest::TestConditionsMultiLine));
|
||||
@ -207,6 +319,20 @@ SettingsParserTest::AddTests(BTestSuite& parent)
|
||||
"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);
|
||||
}
|
||||
|
||||
@ -233,3 +359,14 @@ SettingsParserTest::_ParseCondition(const char* text, BMessage& 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 TestConditionsMultiLineNot();
|
||||
|
||||
void TestRunFlat();
|
||||
void TestRunMultiLine();
|
||||
void TestRunIfThenElseFlat();
|
||||
void TestRunIfThenElseMultiLine();
|
||||
|
||||
static void AddTests(BTestSuite& suite);
|
||||
|
||||
private:
|
||||
status_t _ParseCondition(const char* text,
|
||||
BMessage& message);
|
||||
int32 _ArrayCount(BMessage& message,
|
||||
const char* name);
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user