The beginnings of a launch_daemon for Haiku.

* This will be heavily inspired by Apple's launchd, as well as
  systemd -- for now it really doesn't do a whole lot, though.
* What works so far: the configuration files are read, parsed, and
  the jobs created.
* The jobs are even initialized, and their message ports created.
* BApplication now retrieves a previously created port from the
  launch_daemon for use with BServer.
* Only the registrar actually uses this for now.
This commit is contained in:
Axel Dörfler
2015-07-22 20:39:47 +02:00
parent 5f83ad89eb
commit 1480e5da6f
16 changed files with 816 additions and 27 deletions
+60
View File
@@ -0,0 +1,60 @@
service x-vnd.Haiku-registrar {
launch /system/servers/registrar
create_port
}
service x-vnd.Haiku-app_server {
launch /system/servers/app_server
create_port
}
service x-vnd.Haiku-debug_server {
launch /system/servers/debug_server
}
service x-vnd.Haiku-package_daemon {
launch /system/servers/package_daemon
}
service x-vnd.Haiku-syslog_daemon {
launch /system/servers/syslog_daemon
}
service x-vnd.Haiku-mount_server {
launch /system/servers/mount_server
}
service x-vnd.Haiku-media_server {
launch /system/servers/media_server
no_safemode
}
service x-vnd.Haiku-midi_server {
launch /system/servers/midi_server
no_safemode
}
service x-vnd.Haiku-mail_daemon {
launch /system/servers/mail_daemon -E
no_safemode
}
service x-vnd.Haiku-cddb_daemon {
launch /system/servers/cddb_daemon
no_safemode
}
service x-vnd.Haiku-print_server {
launch /system/servers/print_server
no_safemode
}
service x-vnd.Haiku-notification_server {
launch /system/servers/notification_server
no_safemode
}
service x-vnd.Haiku-power_daemon {
launch /system/servers/power_daemon
no_safemode
}
+2 -1
View File
@@ -101,7 +101,7 @@ private:
friend class BServer; friend class BServer;
BApplication(const char* signature, BApplication(const char* signature,
const char* looperName, const char* looperName, port_id port,
bool initGUI, status_t* error); bool initGUI, status_t* error);
BApplication(uint32 signature); BApplication(uint32 signature);
BApplication(const BApplication&); BApplication(const BApplication&);
@@ -121,6 +121,7 @@ private:
const char* property); const char* property);
void _InitData(const char* signature, bool initGUI, void _InitData(const char* signature, bool initGUI,
status_t* error); status_t* error);
port_id _GetPort(const char* signature);
void BeginRectTracking(BRect r, bool trackWhole); void BeginRectTracking(BRect r, bool trackWhole);
void EndRectTracking(); void EndRectTracking();
status_t _SetupServerAllocator(); status_t _SetupServerAllocator();
+6 -4
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2014 Haiku, Inc. All rights reserved. * Copyright 2001-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -135,14 +135,16 @@ private:
static status_t _LockComplete(BLooper* loop, int32 old, static status_t _LockComplete(BLooper* loop, int32 old,
thread_id this_tid, sem_id sem, thread_id this_tid, sem_id sem,
bigtime_t timeout); bigtime_t timeout);
void _InitData(const char* name, int32 priority, int32 capacity); void _InitData(const char* name, int32 priority,
port_id port, int32 capacity);
void AddMessage(BMessage* msg); void AddMessage(BMessage* msg);
void _AddMessagePriv(BMessage* msg); void _AddMessagePriv(BMessage* msg);
static status_t _task0_(void* arg); static status_t _task0_(void* arg);
void* ReadRawFromPort(int32* code, void* ReadRawFromPort(int32* code,
bigtime_t tout = B_INFINITE_TIMEOUT); bigtime_t timeout = B_INFINITE_TIMEOUT);
BMessage* ReadMessageFromPort(bigtime_t tout = B_INFINITE_TIMEOUT); BMessage* ReadMessageFromPort(
bigtime_t timeout = B_INFINITE_TIMEOUT);
virtual BMessage* ConvertToMessage(void* raw, int32 code); virtual BMessage* ConvertToMessage(void* raw, int32 code);
virtual void task_looper(); virtual void task_looper();
void _QuitRequested(BMessage* msg); void _QuitRequested(BMessage* msg);
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright 2015, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
*/
#ifndef LAUNCH_DAEMON_DEFS_H
#define LAUNCH_DAEMON_DEFS_H
//! launch_daemon interface
#include <Errors.h>
#include <Roster.h>
namespace BPrivate {
#define kLaunchDaemonSignature "application/x-vnd.Haiku-launch_daemon"
#define B_LAUNCH_DAEMON_PORT_NAME "system:launch_daemon"
// message constants
enum {
B_GET_LAUNCH_CONNECTIONS = 'lncc',
};
} // namespace BPrivate
#endif // LAUNCH_DAEMON_DEFS_H
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright 2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _LAUNCH_ROSTER_H
#define _LAUNCH_ROSTER_H
#include <Messenger.h>
class BLaunchRoster {
public:
BLaunchRoster();
~BLaunchRoster();
status_t InitCheck() const;
status_t GetData(const char* signature, BMessage& data);
private:
void _InitMessenger();
private:
BMessenger fMessenger;
uint32 _reserved[5];
};
// global BLaunchRoster instance
extern const BLaunchRoster* be_launch_roster;
#endif // _LAUNCH_ROSTER_H
+2 -1
View File
@@ -17,7 +17,8 @@ public:
BServer(const char* signature, bool initGUI, BServer(const char* signature, bool initGUI,
status_t *error); status_t *error);
BServer(const char* signature, const char* BServer(const char* signature, const char*
looperName, bool initGUI, status_t *error); looperName, port_id port, bool initGUI,
status_t *error);
status_t InitGUIContext(); status_t InitGUIContext();
+27 -8
View File
@@ -40,6 +40,8 @@
#include <AutoLocker.h> #include <AutoLocker.h>
#include <BitmapPrivate.h> #include <BitmapPrivate.h>
#include <DraggerPrivate.h> #include <DraggerPrivate.h>
#include <LaunchDaemonDefs.h>
#include <LaunchRoster.h>
#include <LooperList.h> #include <LooperList.h>
#include <MenuWindow.h> #include <MenuWindow.h>
#include <PicturePrivate.h> #include <PicturePrivate.h>
@@ -259,9 +261,10 @@ BApplication::BApplication(const char* signature, status_t* _error)
BApplication::BApplication(const char* signature, const char* looperName, BApplication::BApplication(const char* signature, const char* looperName,
bool initGUI, status_t* _error) port_id port, bool initGUI, status_t* _error)
: :
BLooper(looperName != NULL ? looperName : kDefaultLooperName) BLooper(B_NORMAL_PRIORITY + 1, port < 0 ? _GetPort(signature) : port,
looperName != NULL ? looperName : kDefaultLooperName)
{ {
_InitData(signature, initGUI, _error); _InitData(signature, initGUI, _error);
} }
@@ -356,8 +359,9 @@ BApplication::_InitData(const char* signature, bool initGUI, status_t* _error)
fAppName = signature; fAppName = signature;
#ifndef RUN_WITHOUT_REGISTRAR #ifndef RUN_WITHOUT_REGISTRAR
bool isRegistrar = signature bool registerApp = signature == NULL
&& strcasecmp(signature, kRegistrarSignature) == 0; || (strcasecmp(signature, kRegistrarSignature) != 0
&& strcasecmp(signature, kLaunchDaemonSignature) != 0);
// get team and thread // get team and thread
team_id team = Team(); team_id team = Team();
thread_id thread = BPrivate::main_thread_for(team); thread_id thread = BPrivate::main_thread_for(team);
@@ -396,7 +400,7 @@ BApplication::_InitData(const char* signature, bool initGUI, status_t* _error)
#ifndef RUN_WITHOUT_REGISTRAR #ifndef RUN_WITHOUT_REGISTRAR
// check whether be_roster is valid // check whether be_roster is valid
if (fInitError == B_OK && !isRegistrar if (fInitError == B_OK && registerApp
&& !BRoster::Private().IsMessengerValid(false)) { && !BRoster::Private().IsMessengerValid(false)) {
printf("FATAL: be_roster is not valid. Is the registrar running?\n"); printf("FATAL: be_roster is not valid. Is the registrar running?\n");
fInitError = B_NO_INIT; fInitError = B_NO_INIT;
@@ -405,7 +409,7 @@ BApplication::_InitData(const char* signature, bool initGUI, status_t* _error)
// check whether or not we are pre-registered // check whether or not we are pre-registered
bool preRegistered = false; bool preRegistered = false;
app_info appInfo; app_info appInfo;
if (fInitError == B_OK && !isRegistrar) { if (fInitError == B_OK && registerApp) {
if (BRoster::Private().IsAppRegistered(&ref, team, 0, &preRegistered, if (BRoster::Private().IsAppRegistered(&ref, team, 0, &preRegistered,
&appInfo) != B_OK) { &appInfo) != B_OK) {
preRegistered = false; preRegistered = false;
@@ -429,8 +433,7 @@ BApplication::_InitData(const char* signature, bool initGUI, status_t* _error)
} else if (fInitError == B_OK) { } else if (fInitError == B_OK) {
// not pre-registered -- try to register the application // not pre-registered -- try to register the application
team_id otherTeam = -1; team_id otherTeam = -1;
// the registrar must not register if (registerApp) {
if (!isRegistrar) {
fInitError = BRoster::Private().AddApplication(signature, &ref, fInitError = BRoster::Private().AddApplication(signature, &ref,
appFlags, team, thread, fMsgPort, true, NULL, &otherTeam); appFlags, team, thread, fMsgPort, true, NULL, &otherTeam);
if (fInitError != B_OK) { if (fInitError != B_OK) {
@@ -525,6 +528,22 @@ DBG(OUT("BApplication::InitData() done\n"));
} }
port_id
BApplication::_GetPort(const char* signature)
{
BLaunchRoster launchRoster;
BMessage data;
status_t status = launchRoster.GetData(signature, data);
if (status == B_OK) {
port_id port = data.GetInt32("port", B_NAME_NOT_FOUND);
if (port >= 0)
return port;
}
return -1;
}
BArchivable* BArchivable*
BApplication::Instantiate(BMessage* data) BApplication::Instantiate(BMessage* data)
{ {
+1
View File
@@ -41,6 +41,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
Handler.cpp Handler.cpp
InitTerminateLibBe.cpp InitTerminateLibBe.cpp
Invoker.cpp Invoker.cpp
LaunchRoster.cpp
LinkReceiver.cpp LinkReceiver.cpp
LinkSender.cpp LinkSender.cpp
Looper.cpp Looper.cpp
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright 2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
*/
#include <LaunchRoster.h>
#include <LaunchDaemonDefs.h>
#include <MessengerPrivate.h>
using namespace BPrivate;
const BLaunchRoster* be_launch_roster;
BLaunchRoster::BLaunchRoster()
{
_InitMessenger();
}
BLaunchRoster::~BLaunchRoster()
{
}
status_t
BLaunchRoster::InitCheck() const
{
return fMessenger.Team() >= 0 ? B_OK : B_ERROR;
}
status_t
BLaunchRoster::GetData(const char* signature, BMessage& data)
{
if (signature == NULL || signature[0] == '\0')
return B_BAD_VALUE;
BMessage request(B_GET_LAUNCH_CONNECTIONS);
status_t status = request.AddString("name", signature);
if (status != B_OK)
return status;
// send the request
status = fMessenger.SendMessage(&request, &data);
// evaluate the reply
if (status == B_OK)
status = data.GetInt32("error", B_OK);
return status;
}
void
BLaunchRoster::_InitMessenger()
{
// find the launch_daemon port
port_id daemonPort = find_port(B_LAUNCH_DAEMON_PORT_NAME);
port_info info;
if (daemonPort >= 0 && get_port_info(daemonPort, &info) == B_OK) {
BMessenger::Private(fMessenger).SetTo(info.team, daemonPort,
B_PREFERRED_TOKEN);
}
}
+9 -7
View File
@@ -110,7 +110,7 @@ BLooper::BLooper(const char* name, int32 priority, int32 portCapacity)
: :
BHandler(name) BHandler(name)
{ {
_InitData(name, priority, portCapacity); _InitData(name, priority, -1, portCapacity);
} }
@@ -183,7 +183,7 @@ BLooper::BLooper(BMessage* data)
if (data->FindInt32("_prio", &priority) != B_OK) if (data->FindInt32("_prio", &priority) != B_OK)
priority = B_NORMAL_PRIORITY; priority = B_NORMAL_PRIORITY;
_InitData(Name(), priority, portCapacity); _InitData(Name(), priority, -1, portCapacity);
} }
@@ -827,9 +827,7 @@ BLooper::operator=(const BLooper& other)
BLooper::BLooper(int32 priority, port_id port, const char* name) BLooper::BLooper(int32 priority, port_id port, const char* name)
{ {
// This must be a legacy constructor _InitData(name, priority, port, B_LOOPER_PORT_DEFAULT_CAPACITY);
fMsgPort = port;
_InitData(name, priority, B_LOOPER_PORT_DEFAULT_CAPACITY);
} }
@@ -935,7 +933,8 @@ BLooper::_LockComplete(BLooper* looper, int32 oldCount, thread_id thread,
void void
BLooper::_InitData(const char* name, int32 priority, int32 portCapacity) BLooper::_InitData(const char* name, int32 priority, port_id port,
int32 portCapacity)
{ {
fOwner = B_ERROR; fOwner = B_ERROR;
fCachedStack = 0; fCachedStack = 0;
@@ -961,7 +960,10 @@ BLooper::_InitData(const char* name, int32 priority, int32 portCapacity)
if (portCapacity <= 0) if (portCapacity <= 0)
portCapacity = B_LOOPER_PORT_DEFAULT_CAPACITY; portCapacity = B_LOOPER_PORT_DEFAULT_CAPACITY;
fMsgPort = create_port(portCapacity, name); if (port >= 0)
fMsgPort = port;
else
fMsgPort = create_port(portCapacity, name);
fInitPriority = priority; fInitPriority = priority;
+4 -4
View File
@@ -13,17 +13,17 @@
BServer::BServer(const char* signature, bool initGUI, status_t *error) BServer::BServer(const char* signature, bool initGUI, status_t *error)
: :
BApplication(signature, NULL, initGUI, error), BApplication(signature, NULL, -1, initGUI, error),
fGUIContextInitialized(false) fGUIContextInitialized(false)
{ {
fGUIContextInitialized = initGUI && (error == NULL || *error == B_OK); fGUIContextInitialized = initGUI && (error == NULL || *error == B_OK);
} }
BServer::BServer(const char* signature, const char* looperName, bool initGUI, BServer::BServer(const char* signature, const char* looperName, port_id port,
status_t *error) bool initGUI, status_t *error)
: :
BApplication(signature, looperName, initGUI, error), BApplication(signature, looperName, port, initGUI, error),
fGUIContextInitialized(false) fGUIContextInitialized(false)
{ {
fGUIContextInitialized = initGUI && (error == NULL || *error == B_OK); fGUIContextInitialized = initGUI && (error == NULL || *error == B_OK);
+1
View File
@@ -7,6 +7,7 @@ SubInclude HAIKU_TOP src servers debug ;
SubInclude HAIKU_TOP src servers index ; SubInclude HAIKU_TOP src servers index ;
SubInclude HAIKU_TOP src servers input ; SubInclude HAIKU_TOP src servers input ;
SubInclude HAIKU_TOP src servers keystore ; SubInclude HAIKU_TOP src servers keystore ;
SubInclude HAIKU_TOP src servers launch ;
SubInclude HAIKU_TOP src servers mail ; SubInclude HAIKU_TOP src servers mail ;
SubInclude HAIKU_TOP src servers media ; SubInclude HAIKU_TOP src servers media ;
SubInclude HAIKU_TOP src servers media_addon ; SubInclude HAIKU_TOP src servers media_addon ;
+13
View File
@@ -0,0 +1,13 @@
SubDir HAIKU_TOP src servers launch ;
UsePrivateHeaders app shared ;
UsePrivateSystemHeaders ;
Server launch_daemon
:
LaunchDaemon.cpp
:
be libshared.a [ TargetLibstdc++ ]
:
LaunchDaemon.rdef
;
+534
View File
@@ -0,0 +1,534 @@
/*
* Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <Directory.h>
#include <driver_settings.h>
#include <Entry.h>
#include <ObjectList.h>
#include <Path.h>
#include <PathFinder.h>
#include <Server.h>
#include <DriverSettingsMessageAdapter.h>
#include <LaunchDaemonDefs.h>
#include <syscalls.h>
using namespace BPrivate;
static const char* kLaunchDirectory = "launch";
const static settings_template kJobTemplate[] = {
{B_STRING_TYPE, "name", NULL, true},
{B_BOOL_TYPE, "disabled", NULL},
{B_STRING_TYPE, "launch", NULL},
{B_BOOL_TYPE, "create_port", NULL},
{B_BOOL_TYPE, "no_safemode", NULL},
{0, NULL, NULL}
};
const static settings_template kSettingsTemplate[] = {
{B_MESSAGE_TYPE, "job", kJobTemplate},
{B_MESSAGE_TYPE, "service", kJobTemplate},
{0, NULL, NULL}
};
class Job {
public:
Job(const char* name);
virtual ~Job();
const char* Name() const;
bool IsEnabled() const;
void SetEnabled(bool enable);
bool IsService() const;
void SetService(bool service);
bool CreatePort() const;
void SetCreatePort(bool createPort);
bool LaunchInSafeMode() const;
void SetLaunchInSafeMode(bool launch);
const BStringList& Arguments() const;
BStringList& Arguments();
void AddArgument(const char* argument);
status_t Init();
status_t InitCheck() const;
port_id Port() const;
status_t Launch();
bool IsLaunched() const;
private:
BString fName;
BStringList fArguments;
bool fEnabled;
bool fService;
bool fCreatePort;
bool fLaunchInSafeMode;
port_id fPort;
status_t fInitStatus;
team_id fTeam;
};
typedef std::map<BString, Job*> JobMap;
class LaunchDaemon : public BServer {
public:
LaunchDaemon(status_t& error);
virtual ~LaunchDaemon();
virtual void ReadyToRun();
virtual void MessageReceived(BMessage* message);
private:
void _ReadPaths(const BStringList& paths);
void _ReadEntry(const char* context, BEntry& entry);
void _ReadDirectory(const char* context,
BEntry& directory);
status_t _ReadFile(const char* context, BEntry& entry);
void _AddJob(bool service, BMessage& message);
Job* _Job(const char* name);
void _InitJobs();
void _LaunchJobs();
void _SetupEnvironment();
bool _IsSafeMode() const;
private:
JobMap fJobs;
};
static const char*
get_leaf(const char* signature)
{
const char* separator = strrchr(signature, '/');
if (separator != NULL)
return separator + 1;
return signature;
}
// #pragma mark -
Job::Job(const char* name)
:
fName(name),
fEnabled(true),
fService(false),
fCreatePort(false),
fLaunchInSafeMode(true),
fPort(-1),
fInitStatus(B_NO_INIT),
fTeam(-1)
{
}
Job::~Job()
{
if (fPort >= 0)
delete_port(fPort);
}
const char*
Job::Name() const
{
return fName.String();
}
bool
Job::IsEnabled() const
{
return fEnabled;
}
void
Job::SetEnabled(bool enable)
{
fEnabled = enable;
}
bool
Job::IsService() const
{
return fService;
}
void
Job::SetService(bool service)
{
fService = service;
}
bool
Job::CreatePort() const
{
return fCreatePort;
}
void
Job::SetCreatePort(bool createPort)
{
fCreatePort = createPort;
}
bool
Job::LaunchInSafeMode() const
{
return fLaunchInSafeMode;
}
void
Job::SetLaunchInSafeMode(bool launch)
{
fLaunchInSafeMode = launch;
}
const BStringList&
Job::Arguments() const
{
return fArguments;
}
BStringList&
Job::Arguments()
{
return fArguments;
}
void
Job::AddArgument(const char* argument)
{
fArguments.Add(argument);
}
status_t
Job::Init()
{
fInitStatus = B_OK;
if (fCreatePort) {
// TODO: prefix system ports with "system:"
fPort = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name());
if (fPort < 0)
fInitStatus = fPort;
printf("PORT %s: %s\n", Name(), strerror(fPort));
}
return fInitStatus;
}
status_t
Job::InitCheck() const
{
return fInitStatus;
}
port_id
Job::Port() const
{
return fPort;
}
status_t
Job::Launch()
{
if (fArguments.IsEmpty()) {
// TODO: launch via signature
} else {
printf("LAUNCH %s\n", fArguments.StringAt(0).String());
}
return B_OK;
}
bool
Job::IsLaunched() const
{
return fTeam >= 0;
}
// #pragma mark -
LaunchDaemon::LaunchDaemon(status_t& error)
:
BServer(kLaunchDaemonSignature, NULL,
create_port(B_LOOPER_PORT_DEFAULT_CAPACITY,
B_LAUNCH_DAEMON_PORT_NAME), false, &error)
{
}
LaunchDaemon::~LaunchDaemon()
{
}
void
LaunchDaemon::ReadyToRun()
{
_SetupEnvironment();
BStringList paths;
BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, kLaunchDirectory,
B_FIND_PATHS_SYSTEM_ONLY, paths);
_ReadPaths(paths);
BPathFinder::FindPaths(B_FIND_PATH_SETTINGS_DIRECTORY, kLaunchDirectory,
B_FIND_PATHS_SYSTEM_ONLY, paths);
_ReadPaths(paths);
_InitJobs();
_LaunchJobs();
}
void
LaunchDaemon::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_GET_LAUNCH_CONNECTIONS:
{
BMessage reply;
Job* job = _Job(get_leaf(message->GetString("name")));
if (job == NULL) {
reply.AddInt32("error", B_NAME_NOT_FOUND);
} else {
if (job->CreatePort())
reply.AddInt32("port", job->Port());
// Launch job now if it isn't running yet
if (!job->IsLaunched())
job->Launch();
}
message->SendReply(&reply);
break;
}
default:
BServer::MessageReceived(message);
break;
}
}
void
LaunchDaemon::_ReadPaths(const BStringList& paths)
{
for (int32 i = 0; i < paths.CountStrings(); i++) {
printf("----- %s -------\n", paths.StringAt(i).String());
BEntry entry(paths.StringAt(i));
if (entry.InitCheck() != B_OK || !entry.Exists())
continue;
_ReadDirectory(NULL, entry);
}
}
void
LaunchDaemon::_ReadEntry(const char* context, BEntry& entry)
{
if (entry.IsDirectory())
_ReadDirectory(context, entry);
else
_ReadFile(context, entry);
}
void
LaunchDaemon::_ReadDirectory(const char* context, BEntry& directoryEntry)
{
BDirectory directory(&directoryEntry);
printf("DIR %s\n", directoryEntry.Name());
BEntry entry;
while (directory.GetNextEntry(&entry) == B_OK) {
_ReadEntry(context, entry);
}
}
status_t
LaunchDaemon::_ReadFile(const char* context, BEntry& entry)
{
printf("FILE %s\n", entry.Name());
DriverSettingsMessageAdapter adapter;
BPath path;
status_t status = path.SetTo(&entry);
if (status != B_OK)
return status;
BMessage message;
status = adapter.ConvertFromDriverSettings(path.Path(), kSettingsTemplate,
message);
if (status == B_OK) {
message.PrintToStream();
BMessage job;
for (int32 index = 0; message.FindMessage("service", index,
&job) == B_OK; index++) {
_AddJob(false, job);
}
for (int32 index = 0; message.FindMessage("job", index, &job) == B_OK;
index++) {
_AddJob(false, job);
}
}
return status;
}
void
LaunchDaemon::_AddJob(bool service, BMessage& message)
{
const char* name = message.GetString("name");
printf("JOB %s\n", name);
if (name == NULL || name[0] == '\0') {
// Invalid job description
return;
}
Job* job = _Job(name);
if (job == NULL)
job = new Job(name);
job->SetEnabled(!message.GetBool("disabled", !job->IsEnabled()));
job->SetService(service);
job->SetCreatePort(message.GetBool("create_port", job->CreatePort()));
job->SetLaunchInSafeMode(
!message.GetBool("no_safemode", !job->LaunchInSafeMode()));
const char* argument;
for (int32 index = 0;
message.FindString("launch", index, &argument) == B_OK; index++) {
job->AddArgument(argument);
}
fJobs.insert(std::pair<BString, Job*>(job->Name(), job));
}
Job*
LaunchDaemon::_Job(const char* name)
{
if (name == NULL)
return NULL;
JobMap::const_iterator found = fJobs.find(name);
if (found != fJobs.end())
return found->second;
return NULL;
}
void
LaunchDaemon::_InitJobs()
{
for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();
iterator++) {
Job* job = iterator->second;
printf(" enabled? %s - %d\n", job->Name(), job->IsEnabled());
if (job->IsEnabled() && (!_IsSafeMode() || job->LaunchInSafeMode()))
job->Init();
}
}
void
LaunchDaemon::_LaunchJobs()
{
for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();
iterator++) {
Job* job = iterator->second;
if (job->IsEnabled() && job->InitCheck() == B_OK)
job->Launch();
}
}
void
LaunchDaemon::_SetupEnvironment()
{
// Determine safemode kernel option
BString safemode = "SAFEMODE=";
safemode << _IsSafeMode() ? "yes" : "no";
}
bool
LaunchDaemon::_IsSafeMode() const
{
char buffer[32];
size_t size = sizeof(buffer);
status_t status = _kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, buffer,
&size);
if (status == B_OK) {
return !strncasecmp(buffer, "true", size)
|| !strncasecmp(buffer, "yes", size)
|| !strncasecmp(buffer, "on", size)
|| !strncasecmp(buffer, "enabled", size);
}
return false;
}
// #pragma mark -
int
main()
{
status_t status;
LaunchDaemon* daemon = new LaunchDaemon(status);
if (status == B_OK)
daemon->Run();
delete daemon;
return status == B_OK ? EXIT_SUCCESS : EXIT_FAILURE;
}
+15
View File
@@ -0,0 +1,15 @@
resource app_signature "application/x-vnd.haiku-launch_daemon";
resource app_flags B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP;
resource app_version {
major = 1,
middle = 0,
minor = 0,
variety = B_APPV_ALPHA,
internal = 0,
short_info = "launch_daemon",
long_info = "launch_daemon ©2015 Haiku Inc."
};
+2 -2
View File
@@ -57,8 +57,8 @@ static const bigtime_t kRosterSanityEventInterval = 1000000LL;
*/ */
Registrar::Registrar(status_t* _error) Registrar::Registrar(status_t* _error)
: :
BServer(kRegistrarSignature, BPrivate::get_roster_port_name(), false, BServer(kRegistrarSignature, BPrivate::get_roster_port_name(), -1,
_error), false, _error),
fRoster(NULL), fRoster(NULL),
fClipboardHandler(NULL), fClipboardHandler(NULL),
fMIMEManager(NULL), fMIMEManager(NULL),