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
Private(BLaunchRoster * roster)25 BLaunchRoster::Private::Private(BLaunchRoster* roster)
26 :
27 fRoster(roster)
28 {
29 }
30
31
Private(BLaunchRoster & roster)32 BLaunchRoster::Private::Private(BLaunchRoster& roster)
33 :
34 fRoster(&roster)
35 {
36 }
37
38
39 status_t
RegisterSessionDaemon(const BMessenger & daemon)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
BLaunchRoster()64 BLaunchRoster::BLaunchRoster()
65 {
66 _InitMessenger();
67 }
68
69
~BLaunchRoster()70 BLaunchRoster::~BLaunchRoster()
71 {
72 }
73
74
75 status_t
InitCheck() const76 BLaunchRoster::InitCheck() const
77 {
78 return fMessenger.Team() >= 0 ? B_OK : B_ERROR;
79 }
80
81
82 status_t
GetData(BMessage & data)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
GetData(const char * signature,BMessage & data)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
GetPort(const char * name)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
GetPort(const char * signature,const char * name)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
Target(const char * name,const BMessage & data,const char * baseName)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
Target(const char * name,const BMessage * data,const char * baseName)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
StopTarget(const char * name,bool force)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
Start(const char * name)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
Stop(const char * name,bool force)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
SetEnabled(const char * name,bool enable)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
StartSession(const char * login)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
RegisterEvent(const BMessenger & source,const char * name,uint32 flags)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
UnregisterEvent(const BMessenger & source,const char * name)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
NotifyEvent(const BMessenger & source,const char * name)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
ResetStickyEvent(const BMessenger & source,const char * name)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
GetTargets(BStringList & targets)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
GetTargetInfo(const char * name,BMessage & info)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
GetJobs(const char * target,BStringList & jobs)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
GetJobInfo(const char * name,BMessage & info)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
GetLog(BMessage & info)342 BLaunchRoster::GetLog(BMessage& info)
343 {
344 return _GetLog(NULL, info);
345 }
346
347
348 status_t
GetLog(const BMessage & filter,BMessage & info)349 BLaunchRoster::GetLog(const BMessage& filter, BMessage& info)
350 {
351 return _GetLog(&filter, info);
352 }
353
354
355 void
_InitMessenger()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
_SendRequest(BMessage & request)373 BLaunchRoster::_SendRequest(BMessage& request)
374 {
375 BMessage result;
376 return _SendRequest(request, result);
377 }
378
379
380 status_t
_SendRequest(BMessage & request,BMessage & result)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
_UpdateEvent(uint32 what,const BMessenger & source,const char * name,uint32 flags)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
_GetInfo(uint32 what,const char * name,BMessage & info)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
_GetLog(const BMessage * filter,BMessage & info)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