launch_daemon: Moved Job+Target into separate files.
This commit is contained in:
@@ -8,6 +8,8 @@ UseHeaders [ FDirName $(HAIKU_TOP) src bin multiuser ] ;
|
|||||||
Server launch_daemon
|
Server launch_daemon
|
||||||
:
|
:
|
||||||
LaunchDaemon.cpp
|
LaunchDaemon.cpp
|
||||||
|
Job.cpp
|
||||||
|
Target.cpp
|
||||||
Worker.cpp
|
Worker.cpp
|
||||||
|
|
||||||
# init jobs
|
# init jobs
|
||||||
|
|||||||
@@ -0,0 +1,407 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Job.h"
|
||||||
|
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <Looper.h>
|
||||||
|
#include <Message.h>
|
||||||
|
|
||||||
|
#include "Target.h"
|
||||||
|
|
||||||
|
|
||||||
|
Job::Job(const char* name)
|
||||||
|
:
|
||||||
|
BJob(name),
|
||||||
|
fEnabled(true),
|
||||||
|
fService(false),
|
||||||
|
fCreateDefaultPort(false),
|
||||||
|
fLaunchInSafeMode(true),
|
||||||
|
fInitStatus(B_NO_INIT),
|
||||||
|
fTeam(-1),
|
||||||
|
fTarget(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Job::Job(const Job& other)
|
||||||
|
:
|
||||||
|
BJob(other.Name()),
|
||||||
|
fEnabled(other.IsEnabled()),
|
||||||
|
fService(other.IsService()),
|
||||||
|
fCreateDefaultPort(other.CreateDefaultPort()),
|
||||||
|
fLaunchInSafeMode(other.LaunchInSafeMode()),
|
||||||
|
fInitStatus(B_NO_INIT),
|
||||||
|
fTeam(-1),
|
||||||
|
fTarget(other.Target())
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < other.Arguments().CountStrings(); i++)
|
||||||
|
AddArgument(other.Arguments().StringAt(i));
|
||||||
|
|
||||||
|
for (int32 i = 0; i < other.Requirements().CountStrings(); i++)
|
||||||
|
AddRequirement(other.Requirements().StringAt(i));
|
||||||
|
|
||||||
|
PortMap::const_iterator constIterator = other.Ports().begin();
|
||||||
|
for (; constIterator != other.Ports().end(); constIterator++) {
|
||||||
|
fPortMap.insert(
|
||||||
|
std::make_pair(constIterator->first, constIterator->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
PortMap::iterator iterator = fPortMap.begin();
|
||||||
|
for (; iterator != fPortMap.end(); iterator++)
|
||||||
|
iterator->second.RemoveData("port");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Job::~Job()
|
||||||
|
{
|
||||||
|
_DeletePorts();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
Job::Name() const
|
||||||
|
{
|
||||||
|
return Title().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::CreateDefaultPort() const
|
||||||
|
{
|
||||||
|
return fCreateDefaultPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Job::SetCreateDefaultPort(bool createPort)
|
||||||
|
{
|
||||||
|
fCreateDefaultPort = createPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Job::AddPort(BMessage& data)
|
||||||
|
{
|
||||||
|
const char* name = data.GetString("name");
|
||||||
|
fPortMap.insert(std::pair<BString, BMessage>(BString(name), data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
::Target*
|
||||||
|
Job::Target() const
|
||||||
|
{
|
||||||
|
return fTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Job::SetTarget(::Target* target)
|
||||||
|
{
|
||||||
|
fTarget = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BStringList&
|
||||||
|
Job::Requirements() const
|
||||||
|
{
|
||||||
|
return fRequirements;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStringList&
|
||||||
|
Job::Requirements()
|
||||||
|
{
|
||||||
|
return fRequirements;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Job::AddRequirement(const char* requirement)
|
||||||
|
{
|
||||||
|
fRequirements.Add(requirement);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Job::Init(const Finder& finder, std::set<BString>& dependencies)
|
||||||
|
{
|
||||||
|
// Only initialize the jobs once
|
||||||
|
if (fInitStatus != B_NO_INIT)
|
||||||
|
return fInitStatus;
|
||||||
|
|
||||||
|
fInitStatus = B_OK;
|
||||||
|
|
||||||
|
if (fTarget != NULL)
|
||||||
|
fTarget->AddDependency(this);
|
||||||
|
|
||||||
|
// Check dependencies
|
||||||
|
|
||||||
|
for (int32 index = 0; index < Requirements().CountStrings(); index++) {
|
||||||
|
const BString& requires = Requirements().StringAt(index);
|
||||||
|
if (dependencies.find(requires) != dependencies.end()) {
|
||||||
|
// Found a cyclic dependency
|
||||||
|
// TODO: log error
|
||||||
|
return fInitStatus = B_ERROR;
|
||||||
|
}
|
||||||
|
dependencies.insert(requires);
|
||||||
|
|
||||||
|
Job* dependency = finder.FindJob(requires);
|
||||||
|
if (dependency != NULL) {
|
||||||
|
std::set<BString> subDependencies = dependencies;
|
||||||
|
|
||||||
|
fInitStatus = dependency->Init(finder, subDependencies);
|
||||||
|
if (fInitStatus != B_OK) {
|
||||||
|
// TODO: log error
|
||||||
|
return fInitStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
fInitStatus = _AddRequirement(dependency);
|
||||||
|
} else {
|
||||||
|
::Target* target = finder.FindTarget(requires);
|
||||||
|
if (target != NULL)
|
||||||
|
fInitStatus = _AddRequirement(dependency);
|
||||||
|
else {
|
||||||
|
// Could not find dependency
|
||||||
|
fInitStatus = B_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fInitStatus != B_OK) {
|
||||||
|
// TODO: log error
|
||||||
|
return fInitStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create ports
|
||||||
|
// TODO: prefix system ports with "system:"
|
||||||
|
|
||||||
|
bool defaultPort = false;
|
||||||
|
|
||||||
|
for (PortMap::iterator iterator = fPortMap.begin();
|
||||||
|
iterator != fPortMap.end(); iterator++) {
|
||||||
|
BString name(Name());
|
||||||
|
const char* suffix = iterator->second.GetString("name");
|
||||||
|
if (suffix != NULL)
|
||||||
|
name << ':' << suffix;
|
||||||
|
else
|
||||||
|
defaultPort = true;
|
||||||
|
|
||||||
|
const int32 capacity = iterator->second.GetInt32("capacity",
|
||||||
|
B_LOOPER_PORT_DEFAULT_CAPACITY);
|
||||||
|
|
||||||
|
port_id port = create_port(capacity, name.String());
|
||||||
|
if (port < 0) {
|
||||||
|
fInitStatus = port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iterator->second.SetInt32("port", port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fInitStatus == B_OK && fCreateDefaultPort && !defaultPort) {
|
||||||
|
BMessage data;
|
||||||
|
data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY);
|
||||||
|
|
||||||
|
port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name());
|
||||||
|
if (port < 0) {
|
||||||
|
// TODO: log error
|
||||||
|
fInitStatus = port;
|
||||||
|
} else {
|
||||||
|
data.SetInt32("port", port);
|
||||||
|
AddPort(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fInitStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Job::InitCheck() const
|
||||||
|
{
|
||||||
|
return fInitStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
team_id
|
||||||
|
Job::Team() const
|
||||||
|
{
|
||||||
|
return fTeam;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PortMap&
|
||||||
|
Job::Ports() const
|
||||||
|
{
|
||||||
|
return fPortMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
port_id
|
||||||
|
Job::Port(const char* name) const
|
||||||
|
{
|
||||||
|
PortMap::const_iterator found = fPortMap.find(name);
|
||||||
|
if (found != fPortMap.end())
|
||||||
|
return found->second.GetInt32("port", -1);
|
||||||
|
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Job::Launch()
|
||||||
|
{
|
||||||
|
if (fArguments.IsEmpty()) {
|
||||||
|
// TODO: Launch via signature
|
||||||
|
// We cannot use the BRoster here as it tries to pre-register
|
||||||
|
// the application.
|
||||||
|
BString signature("application/");
|
||||||
|
signature << Name();
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
//return be_roster->Launch(signature.String(), (BMessage*)NULL, &fTeam);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_ref ref;
|
||||||
|
status_t status = get_ref_for_path(fArguments.StringAt(0).String(), &ref);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
size_t count = fArguments.CountStrings();
|
||||||
|
const char* args[count + 1];
|
||||||
|
for (int32 i = 0; i < fArguments.CountStrings(); i++) {
|
||||||
|
args[i] = fArguments.StringAt(i);
|
||||||
|
}
|
||||||
|
args[count] = NULL;
|
||||||
|
|
||||||
|
thread_id thread = load_image(count, args,
|
||||||
|
const_cast<const char**>(environ));
|
||||||
|
if (thread >= 0)
|
||||||
|
resume_thread(thread);
|
||||||
|
|
||||||
|
thread_info info;
|
||||||
|
if (get_thread_info(thread, &info) == B_OK)
|
||||||
|
fTeam = info.team;
|
||||||
|
return B_OK;
|
||||||
|
// return be_roster->Launch(&ref, count, args, &fTeam);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Job::IsLaunched() const
|
||||||
|
{
|
||||||
|
return fTeam >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Job::Execute()
|
||||||
|
{
|
||||||
|
if (!IsLaunched())
|
||||||
|
return Launch();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Job::_DeletePorts()
|
||||||
|
{
|
||||||
|
PortMap::const_iterator iterator = Ports().begin();
|
||||||
|
for (; iterator != Ports().end(); iterator++) {
|
||||||
|
port_id port = iterator->second.GetInt32("port", -1);
|
||||||
|
if (port >= 0)
|
||||||
|
delete_port(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Job::_AddRequirement(BJob* dependency)
|
||||||
|
{
|
||||||
|
if (dependency == NULL)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
switch (dependency->State()) {
|
||||||
|
case B_JOB_STATE_WAITING_TO_RUN:
|
||||||
|
case B_JOB_STATE_STARTED:
|
||||||
|
case B_JOB_STATE_IN_PROGRESS:
|
||||||
|
AddDependency(dependency);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JOB_STATE_SUCCEEDED:
|
||||||
|
// Just queue it without any dependencies
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JOB_STATE_FAILED:
|
||||||
|
case B_JOB_STATE_ABORTED:
|
||||||
|
// TODO: return appropriate error
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef JOB_H
|
||||||
|
#define JOB_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Job.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
#include <StringList.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BSupportKit;
|
||||||
|
class BMessage;
|
||||||
|
|
||||||
|
class Finder;
|
||||||
|
class Target;
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map<BString, BMessage> PortMap;
|
||||||
|
|
||||||
|
|
||||||
|
class Job : public BJob {
|
||||||
|
public:
|
||||||
|
Job(const char* name);
|
||||||
|
Job(const Job& other);
|
||||||
|
virtual ~Job();
|
||||||
|
|
||||||
|
const char* Name() const;
|
||||||
|
|
||||||
|
bool IsEnabled() const;
|
||||||
|
void SetEnabled(bool enable);
|
||||||
|
|
||||||
|
bool IsService() const;
|
||||||
|
void SetService(bool service);
|
||||||
|
|
||||||
|
bool CreateDefaultPort() const;
|
||||||
|
void SetCreateDefaultPort(bool createPort);
|
||||||
|
|
||||||
|
void AddPort(BMessage& data);
|
||||||
|
|
||||||
|
bool LaunchInSafeMode() const;
|
||||||
|
void SetLaunchInSafeMode(bool launch);
|
||||||
|
|
||||||
|
const BStringList& Arguments() const;
|
||||||
|
BStringList& Arguments();
|
||||||
|
void AddArgument(const char* argument);
|
||||||
|
|
||||||
|
::Target* Target() const;
|
||||||
|
void SetTarget(::Target* target);
|
||||||
|
|
||||||
|
const BStringList& Requirements() const;
|
||||||
|
BStringList& Requirements();
|
||||||
|
void AddRequirement(const char* requirement);
|
||||||
|
|
||||||
|
status_t Init(const Finder& jobs,
|
||||||
|
std::set<BString>& dependencies);
|
||||||
|
status_t InitCheck() const;
|
||||||
|
|
||||||
|
team_id Team() const;
|
||||||
|
|
||||||
|
const PortMap& Ports() const;
|
||||||
|
port_id Port(const char* name = NULL) const;
|
||||||
|
|
||||||
|
status_t Launch();
|
||||||
|
bool IsLaunched() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual status_t Execute();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Job& operator=(const Job& other);
|
||||||
|
void _DeletePorts();
|
||||||
|
status_t _AddRequirement(BJob* dependency);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BStringList fArguments;
|
||||||
|
BStringList fRequirements;
|
||||||
|
bool fEnabled;
|
||||||
|
bool fService;
|
||||||
|
bool fCreateDefaultPort;
|
||||||
|
bool fLaunchInSafeMode;
|
||||||
|
PortMap fPortMap;
|
||||||
|
status_t fInitStatus;
|
||||||
|
team_id fTeam;
|
||||||
|
::Target* fTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Finder {
|
||||||
|
public:
|
||||||
|
virtual Job* FindJob(const char* name) const = 0;
|
||||||
|
virtual Target* FindTarget(const char* name) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JOB_H
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
#include "InitRealTimeClockJob.h"
|
#include "InitRealTimeClockJob.h"
|
||||||
#include "InitSharedMemoryDirectoryJob.h"
|
#include "InitSharedMemoryDirectoryJob.h"
|
||||||
#include "InitTemporaryDirectoryJob.h"
|
#include "InitTemporaryDirectoryJob.h"
|
||||||
|
#include "Job.h"
|
||||||
|
#include "Target.h"
|
||||||
#include "Worker.h"
|
#include "Worker.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -76,9 +78,6 @@ const static settings_template kSettingsTemplate[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<BString, BMessage> PortMap;
|
|
||||||
|
|
||||||
|
|
||||||
class Session {
|
class Session {
|
||||||
public:
|
public:
|
||||||
Session(uid_t user, const BMessenger& target);
|
Session(uid_t user, const BMessenger& target);
|
||||||
@@ -94,101 +93,6 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Target : public BJob {
|
|
||||||
public:
|
|
||||||
Target(const char* name);
|
|
||||||
|
|
||||||
const char* Name() const;
|
|
||||||
|
|
||||||
status_t AddData(const char* name, BMessage& data);
|
|
||||||
const BMessage& Data() const
|
|
||||||
{ return fData; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual status_t Execute();
|
|
||||||
|
|
||||||
private:
|
|
||||||
BMessage fData;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Finder;
|
|
||||||
|
|
||||||
|
|
||||||
class Job : public BJob {
|
|
||||||
public:
|
|
||||||
Job(const char* name);
|
|
||||||
Job(const Job& other);
|
|
||||||
virtual ~Job();
|
|
||||||
|
|
||||||
const char* Name() const;
|
|
||||||
|
|
||||||
bool IsEnabled() const;
|
|
||||||
void SetEnabled(bool enable);
|
|
||||||
|
|
||||||
bool IsService() const;
|
|
||||||
void SetService(bool service);
|
|
||||||
|
|
||||||
bool CreateDefaultPort() const;
|
|
||||||
void SetCreateDefaultPort(bool createPort);
|
|
||||||
|
|
||||||
void AddPort(BMessage& data);
|
|
||||||
|
|
||||||
bool LaunchInSafeMode() const;
|
|
||||||
void SetLaunchInSafeMode(bool launch);
|
|
||||||
|
|
||||||
const BStringList& Arguments() const;
|
|
||||||
BStringList& Arguments();
|
|
||||||
void AddArgument(const char* argument);
|
|
||||||
|
|
||||||
::Target* Target() const;
|
|
||||||
void SetTarget(::Target* target);
|
|
||||||
|
|
||||||
const BStringList& Requirements() const;
|
|
||||||
BStringList& Requirements();
|
|
||||||
void AddRequirement(const char* requirement);
|
|
||||||
|
|
||||||
status_t Init(const Finder& jobs,
|
|
||||||
std::set<BString>& dependencies);
|
|
||||||
status_t InitCheck() const;
|
|
||||||
|
|
||||||
team_id Team() const;
|
|
||||||
|
|
||||||
const PortMap& Ports() const;
|
|
||||||
port_id Port(const char* name = NULL) const;
|
|
||||||
|
|
||||||
status_t Launch();
|
|
||||||
bool IsLaunched() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual status_t Execute();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Job& operator=(const Job& other);
|
|
||||||
void _DeletePorts();
|
|
||||||
status_t _AddRequirement(BJob* dependency);
|
|
||||||
|
|
||||||
private:
|
|
||||||
BStringList fArguments;
|
|
||||||
BStringList fRequirements;
|
|
||||||
bool fEnabled;
|
|
||||||
bool fService;
|
|
||||||
bool fCreateDefaultPort;
|
|
||||||
bool fLaunchInSafeMode;
|
|
||||||
PortMap fPortMap;
|
|
||||||
status_t fInitStatus;
|
|
||||||
team_id fTeam;
|
|
||||||
::Target* fTarget;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Finder {
|
|
||||||
public:
|
|
||||||
virtual Job* FindJob(const char* name) const = 0;
|
|
||||||
virtual Target* FindTarget(const char* name) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<BString, Job*> JobMap;
|
typedef std::map<BString, Job*> JobMap;
|
||||||
typedef std::map<uid_t, Session*> SessionMap;
|
typedef std::map<uid_t, Session*> SessionMap;
|
||||||
typedef std::map<BString, Target*> TargetMap;
|
typedef std::map<BString, Target*> TargetMap;
|
||||||
@@ -259,403 +163,6 @@ get_leaf(const char* signature)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
Job::Job(const char* name)
|
|
||||||
:
|
|
||||||
BJob(name),
|
|
||||||
fEnabled(true),
|
|
||||||
fService(false),
|
|
||||||
fCreateDefaultPort(false),
|
|
||||||
fLaunchInSafeMode(true),
|
|
||||||
fInitStatus(B_NO_INIT),
|
|
||||||
fTeam(-1),
|
|
||||||
fTarget(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Job::Job(const Job& other)
|
|
||||||
:
|
|
||||||
BJob(other.Name()),
|
|
||||||
fEnabled(other.IsEnabled()),
|
|
||||||
fService(other.IsService()),
|
|
||||||
fCreateDefaultPort(other.CreateDefaultPort()),
|
|
||||||
fLaunchInSafeMode(other.LaunchInSafeMode()),
|
|
||||||
fInitStatus(B_NO_INIT),
|
|
||||||
fTeam(-1),
|
|
||||||
fTarget(other.Target())
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < other.Arguments().CountStrings(); i++)
|
|
||||||
AddArgument(other.Arguments().StringAt(i));
|
|
||||||
|
|
||||||
for (int32 i = 0; i < other.Requirements().CountStrings(); i++)
|
|
||||||
AddRequirement(other.Requirements().StringAt(i));
|
|
||||||
|
|
||||||
PortMap::const_iterator constIterator = other.Ports().begin();
|
|
||||||
for (; constIterator != other.Ports().end(); constIterator++) {
|
|
||||||
fPortMap.insert(
|
|
||||||
std::make_pair(constIterator->first, constIterator->second));
|
|
||||||
}
|
|
||||||
|
|
||||||
PortMap::iterator iterator = fPortMap.begin();
|
|
||||||
for (; iterator != fPortMap.end(); iterator++)
|
|
||||||
iterator->second.RemoveData("port");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Job::~Job()
|
|
||||||
{
|
|
||||||
_DeletePorts();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
|
||||||
Job::Name() const
|
|
||||||
{
|
|
||||||
return Title().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::CreateDefaultPort() const
|
|
||||||
{
|
|
||||||
return fCreateDefaultPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Job::SetCreateDefaultPort(bool createPort)
|
|
||||||
{
|
|
||||||
fCreateDefaultPort = createPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Job::AddPort(BMessage& data)
|
|
||||||
{
|
|
||||||
const char* name = data.GetString("name");
|
|
||||||
fPortMap.insert(std::pair<BString, BMessage>(BString(name), data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
::Target*
|
|
||||||
Job::Target() const
|
|
||||||
{
|
|
||||||
return fTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Job::SetTarget(::Target* target)
|
|
||||||
{
|
|
||||||
fTarget = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const BStringList&
|
|
||||||
Job::Requirements() const
|
|
||||||
{
|
|
||||||
return fRequirements;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BStringList&
|
|
||||||
Job::Requirements()
|
|
||||||
{
|
|
||||||
return fRequirements;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Job::AddRequirement(const char* requirement)
|
|
||||||
{
|
|
||||||
fRequirements.Add(requirement);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Job::Init(const Finder& finder, std::set<BString>& dependencies)
|
|
||||||
{
|
|
||||||
// Only initialize the jobs once
|
|
||||||
if (fInitStatus != B_NO_INIT)
|
|
||||||
return fInitStatus;
|
|
||||||
|
|
||||||
fInitStatus = B_OK;
|
|
||||||
|
|
||||||
if (fTarget != NULL)
|
|
||||||
fTarget->AddDependency(this);
|
|
||||||
|
|
||||||
// Check dependencies
|
|
||||||
|
|
||||||
for (int32 index = 0; index < Requirements().CountStrings(); index++) {
|
|
||||||
const BString& requires = Requirements().StringAt(index);
|
|
||||||
if (dependencies.find(requires) != dependencies.end()) {
|
|
||||||
// Found a cyclic dependency
|
|
||||||
// TODO: log error
|
|
||||||
return fInitStatus = B_ERROR;
|
|
||||||
}
|
|
||||||
dependencies.insert(requires);
|
|
||||||
|
|
||||||
Job* dependency = finder.FindJob(requires);
|
|
||||||
if (dependency != NULL) {
|
|
||||||
std::set<BString> subDependencies = dependencies;
|
|
||||||
|
|
||||||
fInitStatus = dependency->Init(finder, subDependencies);
|
|
||||||
if (fInitStatus != B_OK) {
|
|
||||||
// TODO: log error
|
|
||||||
return fInitStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
fInitStatus = _AddRequirement(dependency);
|
|
||||||
} else {
|
|
||||||
::Target* target = finder.FindTarget(requires);
|
|
||||||
if (target != NULL)
|
|
||||||
fInitStatus = _AddRequirement(dependency);
|
|
||||||
else {
|
|
||||||
// Could not find dependency
|
|
||||||
fInitStatus = B_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fInitStatus != B_OK) {
|
|
||||||
// TODO: log error
|
|
||||||
return fInitStatus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create ports
|
|
||||||
// TODO: prefix system ports with "system:"
|
|
||||||
|
|
||||||
bool defaultPort = false;
|
|
||||||
|
|
||||||
for (PortMap::iterator iterator = fPortMap.begin();
|
|
||||||
iterator != fPortMap.end(); iterator++) {
|
|
||||||
BString name(Name());
|
|
||||||
const char* suffix = iterator->second.GetString("name");
|
|
||||||
if (suffix != NULL)
|
|
||||||
name << ':' << suffix;
|
|
||||||
else
|
|
||||||
defaultPort = true;
|
|
||||||
|
|
||||||
const int32 capacity = iterator->second.GetInt32("capacity",
|
|
||||||
B_LOOPER_PORT_DEFAULT_CAPACITY);
|
|
||||||
|
|
||||||
port_id port = create_port(capacity, name.String());
|
|
||||||
if (port < 0) {
|
|
||||||
fInitStatus = port;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iterator->second.SetInt32("port", port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fInitStatus == B_OK && fCreateDefaultPort && !defaultPort) {
|
|
||||||
BMessage data;
|
|
||||||
data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY);
|
|
||||||
|
|
||||||
port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name());
|
|
||||||
if (port < 0) {
|
|
||||||
// TODO: log error
|
|
||||||
fInitStatus = port;
|
|
||||||
} else {
|
|
||||||
data.SetInt32("port", port);
|
|
||||||
AddPort(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fInitStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Job::InitCheck() const
|
|
||||||
{
|
|
||||||
return fInitStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
team_id
|
|
||||||
Job::Team() const
|
|
||||||
{
|
|
||||||
return fTeam;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const PortMap&
|
|
||||||
Job::Ports() const
|
|
||||||
{
|
|
||||||
return fPortMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
port_id
|
|
||||||
Job::Port(const char* name) const
|
|
||||||
{
|
|
||||||
PortMap::const_iterator found = fPortMap.find(name);
|
|
||||||
if (found != fPortMap.end())
|
|
||||||
return found->second.GetInt32("port", -1);
|
|
||||||
|
|
||||||
return B_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Job::Launch()
|
|
||||||
{
|
|
||||||
if (fArguments.IsEmpty()) {
|
|
||||||
// TODO: Launch via signature
|
|
||||||
// We cannot use the BRoster here as it tries to pre-register
|
|
||||||
// the application.
|
|
||||||
BString signature("application/");
|
|
||||||
signature << Name();
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
//return be_roster->Launch(signature.String(), (BMessage*)NULL, &fTeam);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry_ref ref;
|
|
||||||
status_t status = get_ref_for_path(fArguments.StringAt(0).String(), &ref);
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
size_t count = fArguments.CountStrings();
|
|
||||||
const char* args[count + 1];
|
|
||||||
for (int32 i = 0; i < fArguments.CountStrings(); i++) {
|
|
||||||
args[i] = fArguments.StringAt(i);
|
|
||||||
}
|
|
||||||
args[count] = NULL;
|
|
||||||
|
|
||||||
thread_id thread = load_image(count, args,
|
|
||||||
const_cast<const char**>(environ));
|
|
||||||
if (thread >= 0)
|
|
||||||
resume_thread(thread);
|
|
||||||
|
|
||||||
thread_info info;
|
|
||||||
if (get_thread_info(thread, &info) == B_OK)
|
|
||||||
fTeam = info.team;
|
|
||||||
return B_OK;
|
|
||||||
// return be_roster->Launch(&ref, count, args, &fTeam);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Job::IsLaunched() const
|
|
||||||
{
|
|
||||||
return fTeam >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Job::Execute()
|
|
||||||
{
|
|
||||||
if (!IsLaunched())
|
|
||||||
return Launch();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Job::_DeletePorts()
|
|
||||||
{
|
|
||||||
PortMap::const_iterator iterator = Ports().begin();
|
|
||||||
for (; iterator != Ports().end(); iterator++) {
|
|
||||||
port_id port = iterator->second.GetInt32("port", -1);
|
|
||||||
if (port >= 0)
|
|
||||||
delete_port(port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Job::_AddRequirement(BJob* dependency)
|
|
||||||
{
|
|
||||||
if (dependency == NULL)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
switch (dependency->State()) {
|
|
||||||
case B_JOB_STATE_WAITING_TO_RUN:
|
|
||||||
case B_JOB_STATE_STARTED:
|
|
||||||
case B_JOB_STATE_IN_PROGRESS:
|
|
||||||
AddDependency(dependency);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_JOB_STATE_SUCCEEDED:
|
|
||||||
// Just queue it without any dependencies
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_JOB_STATE_FAILED:
|
|
||||||
case B_JOB_STATE_ABORTED:
|
|
||||||
// TODO: return appropriate error
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
Session::Session(uid_t user, const BMessenger& daemon)
|
Session::Session(uid_t user, const BMessenger& daemon)
|
||||||
:
|
:
|
||||||
fUser(user),
|
fUser(user),
|
||||||
@@ -667,37 +174,6 @@ Session::Session(uid_t user, const BMessenger& daemon)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
Target::Target(const char* name)
|
|
||||||
:
|
|
||||||
BJob(name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
|
||||||
Target::Name() const
|
|
||||||
{
|
|
||||||
return Title().String();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Target::AddData(const char* name, BMessage& data)
|
|
||||||
{
|
|
||||||
return fData.AddMessage(name, &data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Target::Execute()
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
LaunchDaemon::LaunchDaemon(bool userMode, status_t& error)
|
LaunchDaemon::LaunchDaemon(bool userMode, status_t& error)
|
||||||
:
|
:
|
||||||
BServer(kLaunchDaemonSignature, NULL,
|
BServer(kLaunchDaemonSignature, NULL,
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Target.h"
|
||||||
|
|
||||||
|
|
||||||
|
Target::Target(const char* name)
|
||||||
|
:
|
||||||
|
BJob(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
Target::Name() const
|
||||||
|
{
|
||||||
|
return Title().String();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Target::AddData(const char* name, BMessage& data)
|
||||||
|
{
|
||||||
|
return fData.AddMessage(name, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Target::Execute()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef TARGET_H
|
||||||
|
#define TARGET_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Job.h>
|
||||||
|
#include <Message.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BSupportKit;
|
||||||
|
|
||||||
|
|
||||||
|
class Target : public BJob {
|
||||||
|
public:
|
||||||
|
Target(const char* name);
|
||||||
|
|
||||||
|
const char* Name() const;
|
||||||
|
|
||||||
|
status_t AddData(const char* name, BMessage& data);
|
||||||
|
const BMessage& Data() const
|
||||||
|
{ return fData; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual status_t Execute();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessage fData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TARGET_H
|
||||||
Reference in New Issue
Block a user