1/* 2 * Copyright 2015-2017 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel D��rfler, axeld@pinc-software.de 7 */ 8 9 10#include <LaunchRoster.h> 11 12#include <Application.h> 13#include <String.h> 14#include <StringList.h> 15 16#include <launch.h> 17#include <LaunchDaemonDefs.h> 18#include <LaunchRosterPrivate.h> 19#include <MessengerPrivate.h> 20 21 22using namespace BPrivate; 23 24 25BLaunchRoster::Private::Private(BLaunchRoster* roster) 26 : 27 fRoster(roster) 28{ 29} 30 31 32BLaunchRoster::Private::Private(BLaunchRoster& roster) 33 : 34 fRoster(&roster) 35{ 36} 37 38 39status_t 40BLaunchRoster::Private::RegisterSessionDaemon(const BMessenger& daemon) 41{ 42 BMessage request(B_REGISTER_SESSION_DAEMON); 43 status_t status = request.AddInt32("user", getuid()); 44 if (status == B_OK) 45 status = request.AddMessenger("daemon", daemon); 46 if (status != B_OK) 47 return status; 48 49 // send the request 50 BMessage result; 51 status = fRoster->fMessenger.SendMessage(&request, &result); 52 53 // evaluate the reply 54 if (status == B_OK) 55 status = result.what; 56 57 return status; 58} 59 60 61// #pragma mark - 62 63 64BLaunchRoster::BLaunchRoster() 65{ 66 _InitMessenger(); 67} 68 69 70BLaunchRoster::~BLaunchRoster() 71{ 72} 73 74 75status_t 76BLaunchRoster::InitCheck() const 77{ 78 return fMessenger.Team() >= 0 ? B_OK : B_ERROR; 79} 80 81 82status_t 83BLaunchRoster::GetData(BMessage& data) 84{ 85 if (be_app == NULL) 86 return B_BAD_VALUE; 87 88 return GetData(be_app->Signature(), data); 89} 90 91 92status_t 93BLaunchRoster::GetData(const char* signature, BMessage& data) 94{ 95 if (signature == NULL || signature[0] == '\0') 96 return B_BAD_VALUE; 97 98 BMessage request(B_GET_LAUNCH_DATA); 99 status_t status = request.AddString("name", signature); 100 if (status == B_OK) 101 status = request.AddInt32("user", getuid()); 102 if (status != B_OK) 103 return status; 104 105 return _SendRequest(request, data); 106} 107 108 109port_id 110BLaunchRoster::GetPort(const char* name) 111{ 112 if (be_app == NULL) 113 return B_BAD_VALUE; 114 115 return GetPort(be_app->Signature(), name); 116} 117 118 119port_id 120BLaunchRoster::GetPort(const char* signature, const char* name) 121{ 122 BMessage data; 123 status_t status = GetData(signature, data); 124 if (status == B_OK) { 125 BString fieldName; 126 if (name != NULL) 127 fieldName << name << "_"; 128 fieldName << "port"; 129 130 port_id port = data.GetInt32(fieldName.String(), B_NAME_NOT_FOUND); 131 if (port >= 0) 132 return port; 133 } 134 135 return -1; 136} 137 138 139status_t 140BLaunchRoster::Target(const char* name, const BMessage& data, 141 const char* baseName) 142{ 143 return Target(name, &data, baseName); 144} 145 146 147status_t 148BLaunchRoster::Target(const char* name, const BMessage* data, 149 const char* baseName) 150{ 151 if (name == NULL) 152 return B_BAD_VALUE; 153 154 BMessage request(B_LAUNCH_TARGET); 155 status_t status = request.AddInt32("user", getuid()); 156 if (status == B_OK) 157 status = request.AddString("target", name); 158 if (status == B_OK && data != NULL && !data->IsEmpty()) 159 status = request.AddMessage("data", data); 160 if (status == B_OK && baseName != NULL) 161 status = request.AddString("base target", baseName); 162 if (status != B_OK) 163 return status; 164 165 return _SendRequest(request); 166} 167 168 169status_t 170BLaunchRoster::StopTarget(const char* name, bool force) 171{ 172 if (name == NULL) 173 return B_BAD_VALUE; 174 175 BMessage request(B_STOP_LAUNCH_TARGET); 176 status_t status = request.AddInt32("user", getuid()); 177 if (status == B_OK) 178 status = request.AddString("target", name); 179 if (status == B_OK) 180 status = request.AddBool("force", force); 181 if (status != B_OK) 182 return status; 183 184 return _SendRequest(request); 185} 186 187 188status_t 189BLaunchRoster::Start(const char* name) 190{ 191 if (name == NULL) 192 return B_BAD_VALUE; 193 194 BMessage request(B_LAUNCH_JOB); 195 status_t status = request.AddInt32("user", getuid()); 196 if (status == B_OK) 197 status = request.AddString("name", name); 198 if (status != B_OK) 199 return status; 200 201 return _SendRequest(request); 202} 203 204 205status_t 206BLaunchRoster::Stop(const char* name, bool force) 207{ 208 if (name == NULL) 209 return B_BAD_VALUE; 210 211 BMessage request(B_STOP_LAUNCH_JOB); 212 status_t status = request.AddInt32("user", getuid()); 213 if (status == B_OK) 214 status = request.AddString("name", name); 215 if (status == B_OK) 216 status = request.AddBool("force", force); 217 if (status != B_OK) 218 return status; 219 220 return _SendRequest(request); 221} 222 223 224status_t 225BLaunchRoster::SetEnabled(const char* name, bool enable) 226{ 227 if (name == NULL) 228 return B_BAD_VALUE; 229 230 BMessage request(B_ENABLE_LAUNCH_JOB); 231 status_t status = request.AddInt32("user", getuid()); 232 if (status == B_OK) 233 status = request.AddString("name", name); 234 if (status == B_OK) 235 status = request.AddBool("enable", enable); 236 if (status != B_OK) 237 return status; 238 239 return _SendRequest(request); 240} 241 242 243status_t 244BLaunchRoster::StartSession(const char* login) 245{ 246 if (login == NULL) 247 return B_BAD_VALUE; 248 249 BMessage request(B_LAUNCH_SESSION); 250 status_t status = request.AddInt32("user", getuid()); 251 if (status == B_OK) 252 status = request.AddString("login", login); 253 if (status != B_OK) 254 return status; 255 256 return _SendRequest(request); 257} 258 259 260status_t 261BLaunchRoster::RegisterEvent(const BMessenger& source, const char* name, 262 uint32 flags) 263{ 264 return _UpdateEvent(B_REGISTER_LAUNCH_EVENT, source, name, flags); 265} 266 267 268status_t 269BLaunchRoster::UnregisterEvent(const BMessenger& source, const char* name) 270{ 271 return _UpdateEvent(B_UNREGISTER_LAUNCH_EVENT, source, name); 272} 273 274 275status_t 276BLaunchRoster::NotifyEvent(const BMessenger& source, const char* name) 277{ 278 return _UpdateEvent(B_NOTIFY_LAUNCH_EVENT, source, name); 279} 280 281 282status_t 283BLaunchRoster::ResetStickyEvent(const BMessenger& source, const char* name) 284{ 285 return _UpdateEvent(B_RESET_STICKY_LAUNCH_EVENT, source, name); 286} 287 288 289status_t 290BLaunchRoster::GetTargets(BStringList& targets) 291{ 292 BMessage request(B_GET_LAUNCH_TARGETS); 293 status_t status = request.AddInt32("user", getuid()); 294 if (status != B_OK) 295 return status; 296 297 // send the request 298 BMessage result; 299 status = _SendRequest(request, result); 300 if (status == B_OK) 301 status = result.FindStrings("target", &targets); 302 303 return status; 304} 305 306 307status_t 308BLaunchRoster::GetTargetInfo(const char* name, BMessage& info) 309{ 310 return _GetInfo(B_GET_LAUNCH_TARGET_INFO, name, info); 311} 312 313 314status_t 315BLaunchRoster::GetJobs(const char* target, BStringList& jobs) 316{ 317 BMessage request(B_GET_LAUNCH_JOBS); 318 status_t status = request.AddInt32("user", getuid()); 319 if (status == B_OK && target != NULL) 320 status = request.AddString("target", target); 321 if (status != B_OK) 322 return status; 323 324 // send the request 325 BMessage result; 326 status = _SendRequest(request, result); 327 if (status == B_OK) 328 status = result.FindStrings("job", &jobs); 329 330 return status; 331} 332 333 334status_t 335BLaunchRoster::GetJobInfo(const char* name, BMessage& info) 336{ 337 return _GetInfo(B_GET_LAUNCH_JOB_INFO, name, info); 338} 339 340 341status_t 342BLaunchRoster::GetLog(BMessage& info) 343{ 344 return _GetLog(NULL, info); 345} 346 347 348status_t 349BLaunchRoster::GetLog(const BMessage& filter, BMessage& info) 350{ 351 return _GetLog(&filter, info); 352} 353 354 355void 356BLaunchRoster::_InitMessenger() 357{ 358#ifdef TEST_MODE 359 port_id daemonPort = find_port(B_LAUNCH_DAEMON_PORT_NAME); 360#else 361 // find the launch_daemon port 362 port_id daemonPort = BPrivate::get_launch_daemon_port(); 363#endif 364 port_info info; 365 if (daemonPort >= 0 && get_port_info(daemonPort, &info) == B_OK) { 366 BMessenger::Private(fMessenger).SetTo(info.team, daemonPort, 367 B_PREFERRED_TOKEN); 368 } 369} 370 371 372status_t 373BLaunchRoster::_SendRequest(BMessage& request) 374{ 375 BMessage result; 376 return _SendRequest(request, result); 377} 378 379 380status_t 381BLaunchRoster::_SendRequest(BMessage& request, BMessage& result) 382{ 383 // Send the request, and evaluate the reply 384 status_t status = fMessenger.SendMessage(&request, &result); 385 if (status == B_OK) 386 status = result.what; 387 388 return status; 389} 390 391 392status_t 393BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source, 394 const char* name, uint32 flags) 395{ 396 if (be_app == NULL || name == NULL || name[0] == '\0') 397 return B_BAD_VALUE; 398 399 BMessage request(what); 400 status_t status = request.AddInt32("user", getuid()); 401 if (status == B_OK) 402 status = request.AddMessenger("source", source); 403 if (status == B_OK) 404 status = request.AddString("owner", be_app->Signature()); 405 if (status == B_OK) 406 status = request.AddString("name", name); 407 if (status == B_OK && flags != 0) 408 status = request.AddUInt32("flags", flags); 409 if (status != B_OK) 410 return status; 411 412 return _SendRequest(request); 413} 414 415 416status_t 417BLaunchRoster::_GetInfo(uint32 what, const char* name, BMessage& info) 418{ 419 if (name == NULL || name[0] == '\0') 420 return B_BAD_VALUE; 421 422 BMessage request(what); 423 status_t status = request.AddInt32("user", getuid()); 424 if (status == B_OK) 425 status = request.AddString("name", name); 426 if (status != B_OK) 427 return status; 428 429 return _SendRequest(request, info); 430} 431 432 433status_t 434BLaunchRoster::_GetLog(const BMessage* filter, BMessage& info) 435{ 436 BMessage request(B_GET_LAUNCH_LOG); 437 status_t status = request.AddInt32("user", getuid()); 438 if (status == B_OK && filter != NULL) 439 status = request.AddMessage("filter", filter); 440 if (status != B_OK) 441 return status; 442 443 return _SendRequest(request, info); 444} 445