From 1480e5da6fc4a2926c3da1a973e39927ac2171ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 2 Apr 2015 11:42:35 +0200 Subject: [PATCH] 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. --- data/launch/system | 60 +++ headers/os/app/Application.h | 3 +- headers/os/app/Looper.h | 10 +- headers/private/app/LaunchDaemonDefs.h | 35 ++ headers/private/app/LaunchRoster.h | 33 ++ headers/private/app/Server.h | 3 +- src/kits/app/Application.cpp | 35 +- src/kits/app/Jamfile | 1 + src/kits/app/LaunchRoster.cpp | 72 ++++ src/kits/app/Looper.cpp | 16 +- src/kits/app/Server.cpp | 8 +- src/servers/Jamfile | 1 + src/servers/launch/Jamfile | 13 + src/servers/launch/LaunchDaemon.cpp | 534 +++++++++++++++++++++++++ src/servers/launch/LaunchDaemon.rdef | 15 + src/servers/registrar/Registrar.cpp | 4 +- 16 files changed, 816 insertions(+), 27 deletions(-) create mode 100644 data/launch/system create mode 100644 headers/private/app/LaunchDaemonDefs.h create mode 100644 headers/private/app/LaunchRoster.h create mode 100644 src/kits/app/LaunchRoster.cpp create mode 100644 src/servers/launch/Jamfile create mode 100644 src/servers/launch/LaunchDaemon.cpp create mode 100644 src/servers/launch/LaunchDaemon.rdef diff --git a/data/launch/system b/data/launch/system new file mode 100644 index 0000000000..6e2e88da8e --- /dev/null +++ b/data/launch/system @@ -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 +} diff --git a/headers/os/app/Application.h b/headers/os/app/Application.h index 849b4bf677..ef7881d69e 100644 --- a/headers/os/app/Application.h +++ b/headers/os/app/Application.h @@ -101,7 +101,7 @@ private: friend class BServer; BApplication(const char* signature, - const char* looperName, + const char* looperName, port_id port, bool initGUI, status_t* error); BApplication(uint32 signature); BApplication(const BApplication&); @@ -121,6 +121,7 @@ private: const char* property); void _InitData(const char* signature, bool initGUI, status_t* error); + port_id _GetPort(const char* signature); void BeginRectTracking(BRect r, bool trackWhole); void EndRectTracking(); status_t _SetupServerAllocator(); diff --git a/headers/os/app/Looper.h b/headers/os/app/Looper.h index a4bf958f18..215f7a8c96 100644 --- a/headers/os/app/Looper.h +++ b/headers/os/app/Looper.h @@ -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. * * Authors: @@ -135,14 +135,16 @@ private: static status_t _LockComplete(BLooper* loop, int32 old, thread_id this_tid, sem_id sem, 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 _AddMessagePriv(BMessage* msg); static status_t _task0_(void* arg); void* ReadRawFromPort(int32* code, - bigtime_t tout = B_INFINITE_TIMEOUT); - BMessage* ReadMessageFromPort(bigtime_t tout = B_INFINITE_TIMEOUT); + bigtime_t timeout = B_INFINITE_TIMEOUT); + BMessage* ReadMessageFromPort( + bigtime_t timeout = B_INFINITE_TIMEOUT); virtual BMessage* ConvertToMessage(void* raw, int32 code); virtual void task_looper(); void _QuitRequested(BMessage* msg); diff --git a/headers/private/app/LaunchDaemonDefs.h b/headers/private/app/LaunchDaemonDefs.h new file mode 100644 index 0000000000..3809ae643a --- /dev/null +++ b/headers/private/app/LaunchDaemonDefs.h @@ -0,0 +1,35 @@ +/* + * Copyright 2015, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef LAUNCH_DAEMON_DEFS_H +#define LAUNCH_DAEMON_DEFS_H + + +//! launch_daemon interface + + +#include +#include + + +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 + diff --git a/headers/private/app/LaunchRoster.h b/headers/private/app/LaunchRoster.h new file mode 100644 index 0000000000..bb9c04a7cf --- /dev/null +++ b/headers/private/app/LaunchRoster.h @@ -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 + + +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 diff --git a/headers/private/app/Server.h b/headers/private/app/Server.h index bce3226073..e92bf8547f 100644 --- a/headers/private/app/Server.h +++ b/headers/private/app/Server.h @@ -17,7 +17,8 @@ public: BServer(const char* signature, bool initGUI, status_t *error); BServer(const char* signature, const char* - looperName, bool initGUI, status_t *error); + looperName, port_id port, bool initGUI, + status_t *error); status_t InitGUIContext(); diff --git a/src/kits/app/Application.cpp b/src/kits/app/Application.cpp index 9d51648ba2..902e84a3eb 100644 --- a/src/kits/app/Application.cpp +++ b/src/kits/app/Application.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include #include @@ -259,9 +261,10 @@ BApplication::BApplication(const char* signature, status_t* _error) 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); } @@ -356,8 +359,9 @@ BApplication::_InitData(const char* signature, bool initGUI, status_t* _error) fAppName = signature; #ifndef RUN_WITHOUT_REGISTRAR - bool isRegistrar = signature - && strcasecmp(signature, kRegistrarSignature) == 0; + bool registerApp = signature == NULL + || (strcasecmp(signature, kRegistrarSignature) != 0 + && strcasecmp(signature, kLaunchDaemonSignature) != 0); // get team and thread team_id team = 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 // check whether be_roster is valid - if (fInitError == B_OK && !isRegistrar + if (fInitError == B_OK && registerApp && !BRoster::Private().IsMessengerValid(false)) { printf("FATAL: be_roster is not valid. Is the registrar running?\n"); 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 bool preRegistered = false; app_info appInfo; - if (fInitError == B_OK && !isRegistrar) { + if (fInitError == B_OK && registerApp) { if (BRoster::Private().IsAppRegistered(&ref, team, 0, &preRegistered, &appInfo) != B_OK) { preRegistered = false; @@ -429,8 +433,7 @@ BApplication::_InitData(const char* signature, bool initGUI, status_t* _error) } else if (fInitError == B_OK) { // not pre-registered -- try to register the application team_id otherTeam = -1; - // the registrar must not register - if (!isRegistrar) { + if (registerApp) { fInitError = BRoster::Private().AddApplication(signature, &ref, appFlags, team, thread, fMsgPort, true, NULL, &otherTeam); 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* BApplication::Instantiate(BMessage* data) { diff --git a/src/kits/app/Jamfile b/src/kits/app/Jamfile index c4aea7d68d..8de9740741 100644 --- a/src/kits/app/Jamfile +++ b/src/kits/app/Jamfile @@ -41,6 +41,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { Handler.cpp InitTerminateLibBe.cpp Invoker.cpp + LaunchRoster.cpp LinkReceiver.cpp LinkSender.cpp Looper.cpp diff --git a/src/kits/app/LaunchRoster.cpp b/src/kits/app/LaunchRoster.cpp new file mode 100644 index 0000000000..750df5d4f3 --- /dev/null +++ b/src/kits/app/LaunchRoster.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include + +#include +#include + + +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); + } +} diff --git a/src/kits/app/Looper.cpp b/src/kits/app/Looper.cpp index bee7976137..5b87b08902 100644 --- a/src/kits/app/Looper.cpp +++ b/src/kits/app/Looper.cpp @@ -110,7 +110,7 @@ BLooper::BLooper(const char* name, int32 priority, int32 portCapacity) : 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) 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) { - // This must be a legacy constructor - fMsgPort = port; - _InitData(name, priority, B_LOOPER_PORT_DEFAULT_CAPACITY); + _InitData(name, priority, port, B_LOOPER_PORT_DEFAULT_CAPACITY); } @@ -935,7 +933,8 @@ BLooper::_LockComplete(BLooper* looper, int32 oldCount, thread_id thread, 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; fCachedStack = 0; @@ -961,7 +960,10 @@ BLooper::_InitData(const char* name, int32 priority, int32 portCapacity) if (portCapacity <= 0) portCapacity = B_LOOPER_PORT_DEFAULT_CAPACITY; - fMsgPort = create_port(portCapacity, name); + if (port >= 0) + fMsgPort = port; + else + fMsgPort = create_port(portCapacity, name); fInitPriority = priority; diff --git a/src/kits/app/Server.cpp b/src/kits/app/Server.cpp index 906b254555..614c5628f6 100644 --- a/src/kits/app/Server.cpp +++ b/src/kits/app/Server.cpp @@ -13,17 +13,17 @@ BServer::BServer(const char* signature, bool initGUI, status_t *error) : - BApplication(signature, NULL, initGUI, error), + BApplication(signature, NULL, -1, initGUI, error), fGUIContextInitialized(false) { fGUIContextInitialized = initGUI && (error == NULL || *error == B_OK); } -BServer::BServer(const char* signature, const char* looperName, bool initGUI, - status_t *error) +BServer::BServer(const char* signature, const char* looperName, port_id port, + bool initGUI, status_t *error) : - BApplication(signature, looperName, initGUI, error), + BApplication(signature, looperName, port, initGUI, error), fGUIContextInitialized(false) { fGUIContextInitialized = initGUI && (error == NULL || *error == B_OK); diff --git a/src/servers/Jamfile b/src/servers/Jamfile index 78c893246d..6719cb14db 100644 --- a/src/servers/Jamfile +++ b/src/servers/Jamfile @@ -7,6 +7,7 @@ SubInclude HAIKU_TOP src servers debug ; SubInclude HAIKU_TOP src servers index ; SubInclude HAIKU_TOP src servers input ; SubInclude HAIKU_TOP src servers keystore ; +SubInclude HAIKU_TOP src servers launch ; SubInclude HAIKU_TOP src servers mail ; SubInclude HAIKU_TOP src servers media ; SubInclude HAIKU_TOP src servers media_addon ; diff --git a/src/servers/launch/Jamfile b/src/servers/launch/Jamfile new file mode 100644 index 0000000000..59dd449b1c --- /dev/null +++ b/src/servers/launch/Jamfile @@ -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 +; diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp new file mode 100644 index 0000000000..3542abaad0 --- /dev/null +++ b/src/servers/launch/LaunchDaemon.cpp @@ -0,0 +1,534 @@ +/* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +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 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(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; +} diff --git a/src/servers/launch/LaunchDaemon.rdef b/src/servers/launch/LaunchDaemon.rdef new file mode 100644 index 0000000000..d47ef70fe3 --- /dev/null +++ b/src/servers/launch/LaunchDaemon.rdef @@ -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." +}; diff --git a/src/servers/registrar/Registrar.cpp b/src/servers/registrar/Registrar.cpp index 0a87150513..f905ce3288 100644 --- a/src/servers/registrar/Registrar.cpp +++ b/src/servers/registrar/Registrar.cpp @@ -57,8 +57,8 @@ static const bigtime_t kRosterSanityEventInterval = 1000000LL; */ Registrar::Registrar(status_t* _error) : - BServer(kRegistrarSignature, BPrivate::get_roster_port_name(), false, - _error), + BServer(kRegistrarSignature, BPrivate::get_roster_port_name(), -1, + false, _error), fRoster(NULL), fClipboardHandler(NULL), fMIMEManager(NULL),