void LaunchDaemon::_HandleGetLaunchData(BMessage* message) { uid_t user = _GetUserID(message); if (user < 0) return; BMessage reply((uint32)B_OK); bool launchJob = true; Job* job = FindJob(get_leaf(message->GetString("name"))); if (job == NULL) { Session* session = FindSession(user); if (session != NULL) { // Forward request to user launch_daemon if (session->Daemon().SendMessage(message) == B_OK) return; } reply.what = B_NAME_NOT_FOUND; } else if (job->IsService() && !job->IsLaunched()) { if (job->InitCheck() == B_NO_INIT || !job->CheckCondition(*this)) { // The job exists, but cannot be started yet, as its // conditions are not met; don't make it available yet // TODO: we may not want to initialize jobs with conditions // that aren't met yet reply.what = B_NO_INIT; } else if (job->Event() != NULL) { if (!Events::TriggerDemand(job->Event())) { // The job is not triggered by demand; we cannot start it now reply.what = B_NO_INIT; } else { // The job has already been triggered, don't launch it again launchJob = false; } } } else launchJob = false; bool ownsMessage = false; if (reply.what == B_OK) { // Launch the job if it hasn't been launched already if (launchJob) _LaunchJob(job, TRIGGER_DEMAND); DetachCurrentMessage(); status_t result = job->HandleGetLaunchData(message); if (result == B_OK) { // Replying is delegated to the job. return; } ownsMessage = true; reply.what = result; } message->SendReply(&reply); if (ownsMessage) delete message; }
void LaunchDaemon::_HandleGetLaunchJobInfo(BMessage* message) { uid_t user = _GetUserID(message); if (user < 0) return; const char* name = message->GetString("name"); Job* job = FindJob(name); if (job == NULL && !fUserMode) { _ForwardEventMessage(user, message); return; } BMessage info(uint32(job != NULL ? B_OK : B_NAME_NOT_FOUND)); if (job != NULL) { _GetBaseJobInfo(job, info); info.SetInt32("team", job->Team()); info.SetBool("enabled", job->IsEnabled()); info.SetBool("running", job->IsRunning()); info.SetBool("launched", job->IsLaunched()); info.SetBool("service", job->IsService()); if (job->Target() != NULL) info.SetString("target", job->Target()->Name()); for (int32 i = 0; i < job->Arguments().CountStrings(); i++) info.AddString("launch", job->Arguments().StringAt(i)); for (int32 i = 0; i < job->Requirements().CountStrings(); i++) info.AddString("requires", job->Requirements().StringAt(i)); PortMap::const_iterator iterator = job->Ports().begin(); for (; iterator != job->Ports().end(); iterator++) info.AddMessage("port", &iterator->second); } message->SendReply(&info); }
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; } }