xref: /haiku/src/kits/app/LaunchRoster.cpp (revision a55deaea91d64802ed655d4ffcb41a3519338144)
1 /*
2  * Copyright 2015-2016 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::Start(const char* name)
171 {
172 	if (name == NULL)
173 		return B_BAD_VALUE;
174 
175 	BMessage request(B_LAUNCH_JOB);
176 	status_t status = request.AddInt32("user", getuid());
177 	if (status == B_OK)
178 		status = request.AddString("name", name);
179 	if (status != B_OK)
180 		return status;
181 
182 	return _SendRequest(request);
183 }
184 
185 
186 status_t
187 BLaunchRoster::Stop(const char* name, bool force)
188 {
189 	if (name == NULL)
190 		return B_BAD_VALUE;
191 
192 	BMessage request(B_STOP_LAUNCH_JOB);
193 	status_t status = request.AddInt32("user", getuid());
194 	if (status == B_OK)
195 		status = request.AddString("name", name);
196 	if (status == B_OK)
197 		status = request.AddBool("force", force);
198 	if (status != B_OK)
199 		return status;
200 
201 	return _SendRequest(request);
202 }
203 
204 
205 status_t
206 BLaunchRoster::SetEnabled(const char* name, bool enable)
207 {
208 	if (name == NULL)
209 		return B_BAD_VALUE;
210 
211 	BMessage request(B_ENABLE_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("enable", enable);
217 	if (status != B_OK)
218 		return status;
219 
220 	return _SendRequest(request);
221 }
222 
223 
224 status_t
225 BLaunchRoster::StartSession(const char* login)
226 {
227 	if (login == NULL)
228 		return B_BAD_VALUE;
229 
230 	BMessage request(B_LAUNCH_SESSION);
231 	status_t status = request.AddInt32("user", getuid());
232 	if (status == B_OK)
233 		status = request.AddString("login", login);
234 	if (status != B_OK)
235 		return status;
236 
237 	return _SendRequest(request);
238 }
239 
240 
241 status_t
242 BLaunchRoster::RegisterEvent(const BMessenger& source, const char* name,
243 	uint32 flags)
244 {
245 	return _UpdateEvent(B_REGISTER_LAUNCH_EVENT, source, name, flags);
246 }
247 
248 
249 status_t
250 BLaunchRoster::UnregisterEvent(const BMessenger& source, const char* name)
251 {
252 	return _UpdateEvent(B_UNREGISTER_LAUNCH_EVENT, source, name);
253 }
254 
255 
256 status_t
257 BLaunchRoster::NotifyEvent(const BMessenger& source, const char* name)
258 {
259 	return _UpdateEvent(B_NOTIFY_LAUNCH_EVENT, source, name);
260 }
261 
262 
263 status_t
264 BLaunchRoster::ResetStickyEvent(const BMessenger& source, const char* name)
265 {
266 	return _UpdateEvent(B_RESET_STICKY_LAUNCH_EVENT, source, name);
267 }
268 
269 
270 status_t
271 BLaunchRoster::GetTargets(BStringList& targets)
272 {
273 	BMessage request(B_GET_LAUNCH_TARGETS);
274 	status_t status = request.AddInt32("user", getuid());
275 	if (status != B_OK)
276 		return status;
277 
278 	// send the request
279 	BMessage result;
280 	status = _SendRequest(request, result);
281 	if (status == B_OK)
282 		status = result.FindStrings("target", &targets);
283 
284 	return status;
285 }
286 
287 
288 status_t
289 BLaunchRoster::GetTargetInfo(const char* name, BMessage& info)
290 {
291 	return _GetInfo(B_GET_LAUNCH_TARGET_INFO, name, info);
292 }
293 
294 
295 status_t
296 BLaunchRoster::GetJobs(const char* target, BStringList& jobs)
297 {
298 	BMessage request(B_GET_LAUNCH_JOBS);
299 	status_t status = request.AddInt32("user", getuid());
300 	if (status == B_OK && target != NULL)
301 		status = request.AddString("target", target);
302 	if (status != B_OK)
303 		return status;
304 
305 	// send the request
306 	BMessage result;
307 	status = _SendRequest(request, result);
308 	if (status == B_OK)
309 		status = result.FindStrings("job", &jobs);
310 
311 	return status;
312 }
313 
314 
315 status_t
316 BLaunchRoster::GetJobInfo(const char* name, BMessage& info)
317 {
318 	return _GetInfo(B_GET_LAUNCH_JOB_INFO, name, info);
319 }
320 
321 
322 void
323 BLaunchRoster::_InitMessenger()
324 {
325 	// find the launch_daemon port
326 	port_id daemonPort = BPrivate::get_launch_daemon_port();
327 	port_info info;
328 	if (daemonPort >= 0 && get_port_info(daemonPort, &info) == B_OK) {
329 		BMessenger::Private(fMessenger).SetTo(info.team, daemonPort,
330 			B_PREFERRED_TOKEN);
331 	}
332 }
333 
334 
335 status_t
336 BLaunchRoster::_SendRequest(BMessage& request)
337 {
338 	BMessage result;
339 	return _SendRequest(request, result);
340 }
341 
342 
343 status_t
344 BLaunchRoster::_SendRequest(BMessage& request, BMessage& result)
345 {
346 	// Send the request, and evaluate the reply
347 	status_t status = fMessenger.SendMessage(&request, &result);
348 	if (status == B_OK)
349 		status = result.what;
350 
351 	return status;
352 }
353 
354 
355 status_t
356 BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source,
357 	const char* name, uint32 flags)
358 {
359 	if (be_app == NULL || name == NULL || name[0] == '\0')
360 		return B_BAD_VALUE;
361 
362 	BMessage request(what);
363 	status_t status = request.AddInt32("user", getuid());
364 	if (status == B_OK)
365 		status = request.AddMessenger("source", source);
366 	if (status == B_OK)
367 		status = request.AddString("owner", be_app->Signature());
368 	if (status == B_OK)
369 		status = request.AddString("name", name);
370 	if (status == B_OK && flags != 0)
371 		status = request.AddUInt32("flags", flags);
372 	if (status != B_OK)
373 		return status;
374 
375 	return _SendRequest(request);
376 }
377 
378 
379 status_t
380 BLaunchRoster::_GetInfo(uint32 what, const char* name, BMessage& info)
381 {
382 	if (name == NULL || name[0] == '\0')
383 		return B_BAD_VALUE;
384 
385 	BMessage request(what);
386 	status_t status = request.AddInt32("user", getuid());
387 	if (status == B_OK)
388 		status = request.AddString("name", name);
389 	if (status != B_OK)
390 		return status;
391 
392 	return _SendRequest(request, info);
393 }
394