[haiku-commits] BRANCH axeld-github.launch_daemon [6cadc777073e] src/servers/launch src/kits/app headers/private/app data/launch headers/os/app

  • From: axeld-github.launch_daemon <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 2 Apr 2015 12:01:45 +0200 (CEST)

added 3 changesets to branch 'refs/remotes/axeld-github/launch_daemon'
old head: 0000000000000000000000000000000000000000
new head: 6cadc777073efed5722a6d93fb38dced041a6bce
overview: https://github.com/axeld/haiku/compare/6cadc777073e

----------------------------------------------------------------------------

72e68250583b: Removed old, and unused Netscript.

ce2f552685e5: SetupEnvironment: removed old audio legacy cruft.

* Haiku never supported this.

6cadc777073e: 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.

[ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

20 files changed, 818 insertions(+), 41 deletions(-)
build/jam/packages/Haiku | 2 +-
build/jam/packages/HaikuBootstrap | 2 +-
data/launch/system | 60 ++++
data/system/boot/Netscript | 6 -
data/system/boot/SetupEnvironment | 6 -
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 +-

############################################################################

Commit: 72e68250583b9b2321cf68c03c47255306b91fc2
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Apr 1 14:11:28 2015 UTC

Removed old, and unused Netscript.

----------------------------------------------------------------------------

diff --git a/build/jam/packages/Haiku b/build/jam/packages/Haiku
index 26e4fa0..be3668d 100644
--- a/build/jam/packages/Haiku
+++ b/build/jam/packages/Haiku
@@ -127,7 +127,7 @@ AddSymlinkToPackage bin : gzip : zcat ;
AddSymlinkToPackage bin : zdiff : zcmp ;

# scripts and data files
-local bootScripts = Bootscript Bootscript.cd SetupEnvironment Netscript
+local bootScripts = Bootscript Bootscript.cd SetupEnvironment
InstallerInitScript InstallerFinishScript ;
SEARCH on $(bootScripts) = [ FDirName $(HAIKU_TOP) data system boot ] ;
AddFilesToPackage boot : $(bootScripts) ;
diff --git a/build/jam/packages/HaikuBootstrap
b/build/jam/packages/HaikuBootstrap
index ef610f0..0d6f674 100644
--- a/build/jam/packages/HaikuBootstrap
+++ b/build/jam/packages/HaikuBootstrap
@@ -124,7 +124,7 @@ AddSymlinkToPackage bin : gzip : zcat ;
AddSymlinkToPackage bin : zdiff : zcmp ;

# scripts and data files
-local bootScripts = Bootscript Bootscript.cd SetupEnvironment Netscript
+local bootScripts = Bootscript Bootscript.cd SetupEnvironment
InstallerInitScript InstallerFinishScript ;
SEARCH on $(bootScripts) = [ FDirName $(HAIKU_TOP) data system boot ] ;
AddFilesToPackage boot : $(bootScripts) ;
diff --git a/data/system/boot/Netscript b/data/system/boot/Netscript
deleted file mode 100644
index 6b08919..0000000
--- a/data/system/boot/Netscript
+++ /dev/null
@@ -1,6 +0,0 @@
-# That is a static version of the network interface setup.
-# You have to edit it to match your driver/ip/subnet.
-#ifconfig /dev/net/ipro1000/0 192.168.0.10 up
-
-# This adds the default gateway. Edit it for your needs
-#route add /dev/net/ipro1000/0 default gw 192.168.0.1

############################################################################

Commit: ce2f552685e5b3f2af4393fa0d0c91508430e696
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Apr 1 14:17:00 2015 UTC

SetupEnvironment: removed old audio legacy cruft.

* Haiku never supported this.

----------------------------------------------------------------------------

diff --git a/data/system/boot/SetupEnvironment
b/data/system/boot/SetupEnvironment
index af3cc51..480a824 100644
--- a/data/system/boot/SetupEnvironment
+++ b/data/system/boot/SetupEnvironment
@@ -46,12 +46,6 @@ export LC_COLLATE=$LC_MESSAGES
export LC_CTYPE=$LC_MESSAGES
export LC_MONETARY=$LC_NUMERIC

-# media kit
-if [ -f $HOME/config/settings/use_old_audio ]
-then
- export USE_OLD_AUDIO=true
-fi
-
if [ "$SAFEMODE" != "yes" ]
then
if [ -f $HOME/config/settings/boot/UserSetupEnvironment ]

############################################################################

Commit: 6cadc777073efed5722a6d93fb38dced041a6bce
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Apr 2 09:42:35 2015 UTC

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.

----------------------------------------------------------------------------

diff --git a/data/launch/system b/data/launch/system
new file mode 100644
index 0000000..6e2e88d
--- /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 849b4bf..ef7881d 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 a4bf958..215f7a8 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 0000000..3809ae6
--- /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@xxxxxxxxxxxxxxxx
+ */
+#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
+
diff --git a/headers/private/app/LaunchRoster.h
b/headers/private/app/LaunchRoster.h
new file mode 100644
index 0000000..bb9c04a
--- /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 <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
diff --git a/headers/private/app/Server.h b/headers/private/app/Server.h
index bce3226..e92bf85 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 ff51d2c..1f08b5e 100644
--- a/src/kits/app/Application.cpp
+++ b/src/kits/app/Application.cpp
@@ -40,6 +40,8 @@
#include <AutoLocker.h>
#include <BitmapPrivate.h>
#include <DraggerPrivate.h>
+#include <LaunchDaemonDefs.h>
+#include <LaunchRoster.h>
#include <LooperList.h>
#include <MenuWindow.h>
#include <PicturePrivate.h>
@@ -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) {
@@ -524,6 +527,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 c4aea7d..8de9740 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 0000000..750df5d
--- /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@xxxxxxxxxxxxxxxx
+ */
+
+
+#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);
+ }
+}
diff --git a/src/kits/app/Looper.cpp b/src/kits/app/Looper.cpp
index a47236b..d57b469 100644
--- a/src/kits/app/Looper.cpp
+++ b/src/kits/app/Looper.cpp
@@ -109,7 +109,7 @@ BLooper::BLooper(const char* name, int32 priority, int32
portCapacity)
:
BHandler(name)
{
- _InitData(name, priority, portCapacity);
+ _InitData(name, priority, -1, portCapacity);
}


@@ -182,7 +182,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);
}


@@ -826,9 +826,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);
}


@@ -934,7 +932,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;
@@ -960,7 +959,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 906b254..614c562 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 78c8932..6719cb1 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 0000000..59dd449
--- /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 0000000..3542aba
--- /dev/null
+++ b/src/servers/launch/LaunchDaemon.cpp
@@ -0,0 +1,534 @@
+/*
+ * Copyright 2015, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * 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;
+}
diff --git a/src/servers/launch/LaunchDaemon.rdef
b/src/servers/launch/LaunchDaemon.rdef
new file mode 100644
index 0000000..d47ef70
--- /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 0a87150..f905ce3 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),


Other related posts: