void LaunchDaemon::_HandleGetLaunchTargetInfo(BMessage* message) { uid_t user = _GetUserID(message); if (user < 0) return; const char* name = message->GetString("name"); Target* target = FindTarget(name); if (target == NULL && !fUserMode) { _ForwardEventMessage(user, message); return; } BMessage info(uint32(target != NULL ? B_OK : B_NAME_NOT_FOUND)); if (target != NULL) { _GetBaseJobInfo(target, info); for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end(); iterator++) { Job* job = iterator->second; if (job->Target() == target) info.AddString("job", job->Name()); } } message->SendReply(&info); }
/*! Initializes all jobs for the specified target (may be \c NULL). Jobs that cannot be initialized, and those that never will be due to conditions, will be removed from the list. */ void LaunchDaemon::_InitJobs(Target* target) { for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();) { Job* job = iterator->second; JobMap::iterator remove = iterator++; if (job->Target() != target) continue; status_t status = B_NO_INIT; if (job->IsEnabled()) { // Filter out jobs that have a constant and failing condition if (job->Condition() == NULL || !job->Condition()->IsConstant(*this) || job->Condition()->Test(*this)) { std::set<BString> dependencies; status = job->Init(*this, dependencies); if (status == B_OK && job->Event() != NULL) status = job->Event()->Register(*this); } } if (status != B_OK) { if (status != B_NO_INIT) { // TODO: log error debug_printf("Init \"%s\" failed: %s\n", job->Name(), strerror(status)); } // Remove jobs that won't be used later on fJobs.erase(remove); delete job; } } }
void LaunchDaemon::_HandleLaunchTarget(BMessage* message) { uid_t user = _GetUserID(message); if (user < 0) return; const char* name = message->GetString("target"); const char* baseName = message->GetString("base target"); Target* target = FindTarget(name); if (target == NULL && baseName != NULL) { Target* baseTarget = FindTarget(baseName); if (baseTarget != NULL) { target = new Target(name); // Copy all jobs with the base target into the new target for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();) { Job* job = iterator->second; iterator++; if (job->Target() == baseTarget) { Job* copy = new Job(*job); copy->SetTarget(target); fJobs.insert(std::make_pair(copy->Name(), copy)); } } } } if (target == NULL) { Session* session = FindSession(user); if (session != NULL) { // Forward request to user launch_daemon if (session->Daemon().SendMessage(message) == B_OK) return; } BMessage reply(B_NAME_NOT_FOUND); message->SendReply(&reply); return; } BMessage data; if (message->FindMessage("data", &data) == B_OK) target->AddData(data.GetString("name"), data); _LaunchJobs(target); }
Job::Job(const Job& other) : BaseJob(other.Name()), fEnabled(other.IsEnabled()), fService(other.IsService()), fCreateDefaultPort(other.CreateDefaultPort()), fLaunching(other.IsLaunching()), fInitStatus(B_NO_INIT), fTeam(-1), fDefaultPort(-1), fToken((uint32)B_PREFERRED_TOKEN), fLaunchStatus(B_NO_INIT), fTarget(other.Target()), fPendingLaunchDataReplies(0, false) { mutex_init(&fLaunchStatusLock, "launch status lock"); fCondition = other.fCondition; // TODO: copy events //fEvent = other.fEvent; fEnvironment = other.fEnvironment; fSourceFiles = other.fSourceFiles; 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"); }
void LaunchDaemon::MessageReceived(BMessage* message) { switch (message->what) { case B_SYSTEM_OBJECT_UPDATE: { int32 opcode = message->GetInt32("opcode", 0); team_id team = (team_id)message->GetInt32("team", -1); if (opcode != B_TEAM_DELETED || team < 0) break; MutexLocker locker(fTeamsLock); TeamMap::iterator found = fTeams.find(team); if (found != fTeams.end()) { Job* job = found->second; TRACE("Job %s ended!\n", job->Name()); job->TeamDeleted(); if (job->IsService()) { // TODO: take restart throttle into account // TODO: don't restart on shutdown _LaunchJob(job); } } break; } case B_SOME_APP_LAUNCHED: { team_id team = (team_id)message->GetInt32("be:team", -1); Job* job = NULL; MutexLocker locker(fTeamsLock); TeamMap::iterator found = fTeams.find(team); if (found != fTeams.end()) { job = found->second; locker.Unlock(); } else { locker.Unlock(); // Find job by name instead const char* signature = message->GetString("be:signature"); job = FindJob(get_leaf(signature)); if (job != NULL) { TRACE("Updated default port of untracked team %d, %s\n", (int)team, signature); } } if (job != NULL) { // Update port info app_info info; status_t status = be_roster->GetRunningAppInfo(team, &info); if (status == B_OK && info.port != job->DefaultPort()) { TRACE("Update default port for %s to %d\n", job->Name(), (int)info.port); job->SetDefaultPort(info.port); } } break; } case B_GET_LAUNCH_DATA: _HandleGetLaunchData(message); break; case B_LAUNCH_TARGET: _HandleLaunchTarget(message); break; case B_LAUNCH_JOB: _HandleLaunchJob(message); break; case B_ENABLE_LAUNCH_JOB: _HandleEnableLaunchJob(message); break; case B_STOP_LAUNCH_JOB: _HandleStopLaunchJob(message); break; case B_LAUNCH_SESSION: _HandleLaunchSession(message); break; case B_REGISTER_SESSION_DAEMON: _HandleRegisterSessionDaemon(message); break; case B_REGISTER_LAUNCH_EVENT: _HandleRegisterLaunchEvent(message); break; case B_UNREGISTER_LAUNCH_EVENT: _HandleUnregisterLaunchEvent(message); break; case B_NOTIFY_LAUNCH_EVENT: _HandleNotifyLaunchEvent(message); break; case B_RESET_STICKY_LAUNCH_EVENT: _HandleResetStickyLaunchEvent(message); break; case B_GET_LAUNCH_TARGETS: _HandleGetLaunchTargets(message); break; case B_GET_LAUNCH_TARGET_INFO: _HandleGetLaunchTargetInfo(message); break; case B_GET_LAUNCH_JOBS: _HandleGetLaunchJobs(message); break; case B_GET_LAUNCH_JOB_INFO: _HandleGetLaunchJobInfo(message); break; case kMsgEventTriggered: { // An internal event has been triggered. // Check if its job can be launched now. const char* name = message->GetString("owner"); if (name == NULL) break; Job* job = FindJob(name); if (job != NULL) { _LaunchJob(job); break; } Target* target = FindTarget(name); if (target != NULL) { _LaunchJobs(target); break; } break; } default: BServer::MessageReceived(message); break; } }