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 22 using namespace BPrivate; 23 24 25 BLaunchRoster::Private::Private(BLaunchRoster* roster) 26 : 27 fRoster(roster) 28 { 29 } 30 31 32 BLaunchRoster::Private::Private(BLaunchRoster& roster) 33 : 34 fRoster(&roster) 35 { 36 } 37 38 39 status_t 40 BLaunchRoster::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 64 BLaunchRoster::BLaunchRoster() 65 { 66 _InitMessenger(); 67 } 68 69 70 BLaunchRoster::~BLaunchRoster() 71 { 72 } 73 74 75 status_t 76 BLaunchRoster::InitCheck() const 77 { 78 return fMessenger.Team() >= 0 ? B_OK : B_ERROR; 79 } 80 81 82 status_t 83 BLaunchRoster::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 92 status_t 93 BLaunchRoster::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 109 port_id 110 BLaunchRoster::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 119 port_id 120 BLaunchRoster::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 139 status_t 140 BLaunchRoster::Target(const char* name, const BMessage& data, 141 const char* baseName) 142 { 143 return Target(name, &data, baseName); 144 } 145 146 147 status_t 148 BLaunchRoster::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 169 status_t 170 BLaunchRoster::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 188 status_t 189 BLaunchRoster::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 205 status_t 206 BLaunchRoster::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 224 status_t 225 BLaunchRoster::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 243 status_t 244 BLaunchRoster::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 260 status_t 261 BLaunchRoster::RegisterEvent(const BMessenger& source, const char* name, 262 uint32 flags) 263 { 264 return _UpdateEvent(B_REGISTER_LAUNCH_EVENT, source, name, flags); 265 } 266 267 268 status_t 269 BLaunchRoster::UnregisterEvent(const BMessenger& source, const char* name) 270 { 271 return _UpdateEvent(B_UNREGISTER_LAUNCH_EVENT, source, name); 272 } 273 274 275 status_t 276 BLaunchRoster::NotifyEvent(const BMessenger& source, const char* name) 277 { 278 return _UpdateEvent(B_NOTIFY_LAUNCH_EVENT, source, name); 279 } 280 281 282 status_t 283 BLaunchRoster::ResetStickyEvent(const BMessenger& source, const char* name) 284 { 285 return _UpdateEvent(B_RESET_STICKY_LAUNCH_EVENT, source, name); 286 } 287 288 289 status_t 290 BLaunchRoster::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 307 status_t 308 BLaunchRoster::GetTargetInfo(const char* name, BMessage& info) 309 { 310 return _GetInfo(B_GET_LAUNCH_TARGET_INFO, name, info); 311 } 312 313 314 status_t 315 BLaunchRoster::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 334 status_t 335 BLaunchRoster::GetJobInfo(const char* name, BMessage& info) 336 { 337 return _GetInfo(B_GET_LAUNCH_JOB_INFO, name, info); 338 } 339 340 341 status_t 342 BLaunchRoster::GetLog(BMessage& info) 343 { 344 return _GetLog(NULL, info); 345 } 346 347 348 status_t 349 BLaunchRoster::GetLog(const BMessage& filter, BMessage& info) 350 { 351 return _GetLog(&filter, info); 352 } 353 354 355 void 356 BLaunchRoster::_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 372 status_t 373 BLaunchRoster::_SendRequest(BMessage& request) 374 { 375 BMessage result; 376 return _SendRequest(request, result); 377 } 378 379 380 status_t 381 BLaunchRoster::_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 392 status_t 393 BLaunchRoster::_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 416 status_t 417 BLaunchRoster::_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 433 status_t 434 BLaunchRoster::_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