Moves handling of reloads
[src/app-framework-main.git] / src / afm-user-daemon.c
1 /*
2  Copyright 2015, 2016, 2017 IoT.bzh
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <time.h>
22 #include <getopt.h>
23 #include <string.h>
24
25 #include <systemd/sd-bus.h>
26 #include <systemd/sd-event.h>
27 #include <json-c/json.h>
28
29 #include "verbose.h"
30 #include "utils-jbus.h"
31 #include "utils-json.h"
32 #include "utils-systemd.h"
33 #include "afm.h"
34 #include "afm-launch-mode.h"
35 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
36 # include "afm-db.h"
37 #include "afm-run.h"
38 #else
39 # include "afm-udb.h"
40 #include "afm-urun.h"
41 #endif
42
43 /*
44  * name of the application
45  */
46 static const char appname[] = "afm-user-daemon";
47
48 /*
49  * string for printing usage
50  */
51 static const char usagestr[] =
52 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
53         "usage: %s [-q] [-v] [-m mode] [-r rootdir]... [-a appdir]...\n"
54         "\n"
55         "   -a appdir    adds an application directory\n"
56         "   -r rootdir   adds a root directory of applications\n"
57         "   -m mode      set default launch mode (local or remote)\n"
58 #else
59         "usage: %s [option(s)]\n"
60         "\n"
61 #endif
62         "   -d           run as a daemon\n"
63         "   -u addr      address of user D-Bus to use\n"
64         "   -s addr      address of system D-Bus to use\n"
65         "   -q           quiet\n"
66         "   -v           verbose\n"
67         "\n";
68
69 /*
70  * Option definition for getopt_long
71  */
72 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
73 static const char options_s[] = "hdqvr:a:m:";
74 static struct option options_l[] = {
75         { "root",        required_argument, NULL, 'r' },
76         { "application", required_argument, NULL, 'a' },
77         { "mode",        required_argument, NULL, 'm' },
78 #else
79 static const char options_s[] = "hdqv";
80 static struct option options_l[] = {
81 #endif
82         { "user-dbus",   required_argument, NULL, 'u' },
83         { "system-dbus", required_argument, NULL, 's' },
84         { "daemon",      no_argument,       NULL, 'd' },
85         { "quiet",       no_argument,       NULL, 'q' },
86         { "verbose",     no_argument,       NULL, 'v' },
87         { "help",        no_argument,       NULL, 'h' },
88         { NULL, 0, NULL, 0 }
89 };
90
91 /*
92  * Connections to D-Bus
93  * This is an array for using the function
94  *    jbus_read_write_dispatch_multiple
95  * directly without transformations.
96  */
97 static struct jbus *jbuses[2];
98 #define system_bus  jbuses[0]
99 #define user_bus    jbuses[1]
100
101 /*
102  * Handle to the database of applications
103  */
104 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
105 static struct afm_db *afdb;
106 #else
107 static struct afm_udb *afudb;
108 #endif
109
110 /*
111  * Returned error strings
112  */
113 const char error_nothing[] = "[]";
114 const char error_bad_request[] = "\"bad request\"";
115 const char error_not_found[] = "\"not found\"";
116 const char error_cant_start[] = "\"can't start\"";
117 const char error_system[] = "\"system error\"";
118
119
120 /*
121  * retrieves the 'runid' in 'obj' parameters received with the
122  * request 'smsg' for the 'method'.
123  *
124  * Returns 1 in case of success.
125  * Otherwise, if the 'runid' can't be retrived, an error stating
126  * the bad request is replied for 'smsg' and 0 is returned.
127  */
128 static int onrunid(struct sd_bus_message *smsg, struct json_object *obj,
129                                                 const char *method, int *runid)
130 {
131         if (!j_read_integer(obj, runid)
132                                 && !j_read_integer_at(obj, "runid", runid)) {
133                 INFO("bad request method %s: %s", method,
134                                         json_object_to_json_string(obj));
135                 jbus_reply_error_s(smsg, error_bad_request);
136                 return 0;
137         }
138
139         INFO("method %s called for %d", method, *runid);
140         return 1;
141 }
142
143 /*
144  * Sends the reply 'resp' to the request 'smsg' if 'resp' is not NULL.
145  * Otherwise, when 'resp' is NULL replies the error string 'errstr'.
146  */
147 static void reply(struct sd_bus_message *smsg, struct json_object *resp,
148                                                 const char *errstr)
149 {
150         if (resp)
151                 jbus_reply_j(smsg, resp);
152         else
153                 jbus_reply_error_s(smsg, errstr);
154 }
155
156 /*
157  * Sends the reply "true" to the request 'smsg' if 'status' is zero.
158  * Otherwise, when 'status' is not zero replies the error string 'errstr'.
159  */
160 static void reply_status(struct sd_bus_message *smsg, int status, const char *errstr)
161 {
162         if (status)
163                 jbus_reply_error_s(smsg, errstr);
164         else
165                 jbus_reply_s(smsg, "true");
166 }
167
168 /*
169  * On query "runnables" from 'smsg' with parameters of 'obj'.
170  *
171  * Nothing is expected in 'obj' that can be anything.
172  */
173 static void on_runnables(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
174 {
175         struct json_object *resp;
176         INFO("method runnables called");
177 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
178         resp = afm_db_application_list(afdb);
179 #else
180         resp = afm_udb_applications_public(afudb);
181 #endif
182         jbus_reply_j(smsg, resp);
183         json_object_put(resp);
184 }
185
186 /*
187  * On query "detail" from 'smsg' with parameters of 'obj'.
188  */
189 static void on_detail(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
190 {
191         const char *appid;
192         struct json_object *resp;
193
194         /* get the parameters */
195         if (j_read_string(obj, &appid))
196                 ; /* appid as a string */
197         else if (j_read_string_at(obj, "id", &appid))
198                 ; /* appid as obj.id string */
199         else {
200                 INFO("method detail called but bad request!");
201                 jbus_reply_error_s(smsg, error_bad_request);
202                 return;
203         }
204
205         /* wants details for appid */
206         INFO("method detail called for %s", appid);
207 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
208         resp = afm_db_get_application_public(afdb, appid);
209 #else
210         resp = afm_udb_get_application_public(afudb, appid);
211 #endif
212         reply(smsg, resp, error_not_found);
213         json_object_put(resp);
214 }
215
216 /*
217  * On query "start" from 'smsg' with parameters of 'obj'.
218  */
219 static void on_start(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
220 {
221         const char *appid, *modestr;
222         char *uri;
223         struct json_object *appli, *resp;
224         int runid;
225         char runidstr[20];
226         enum afm_launch_mode mode;
227
228         /* get the parameters */
229         mode = invalid_launch_mode;
230         if (j_read_string(obj, &appid)) {
231                 mode = get_default_launch_mode();
232         } else if (j_read_string_at(obj, "id", &appid)) {
233                 if (j_read_string_at(obj, "mode", &modestr)) {
234                         mode = launch_mode_of_name(modestr);
235                 } else {
236                         mode = get_default_launch_mode();
237                 }
238         }
239         if (!is_valid_launch_mode(mode)) {
240                 jbus_reply_error_s(smsg, error_bad_request);
241                 return;
242         }
243
244         /* get the application */
245         INFO("method start called for %s mode=%s", appid,
246                                                 name_of_launch_mode(mode));
247 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
248         appli = afm_db_get_application(afdb, appid);
249 #else
250         appli = afm_udb_get_application_private(afudb, appid);
251 #endif
252         if (appli == NULL) {
253                 jbus_reply_error_s(smsg, error_not_found);
254                 return;
255         }
256
257         /* launch the application */
258         uri = NULL;
259 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
260         runid = afm_run_start(appli, mode, &uri);
261 #else
262         runid = afm_urun_start(appli);
263 #endif
264         if (runid <= 0) {
265                 jbus_reply_error_s(smsg, error_cant_start);
266                 free(uri);
267                 return;
268         }
269
270         if (uri == NULL) {
271                 /* returns only the runid */
272                 snprintf(runidstr, sizeof runidstr, "%d", runid);
273                 runidstr[sizeof runidstr - 1] = 0;
274                 jbus_reply_s(smsg, runidstr);
275                 return;
276         }
277
278         /* returns the runid and its uri */
279         resp = json_object_new_object();
280         if (resp != NULL && j_add_integer(resp, "runid", runid)
281                                         && j_add_string(resp, "uri", uri))
282                 jbus_reply_j(smsg, resp);
283         else {
284 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
285                 afm_run_terminate(runid);
286 #else
287                 afm_urun_terminate(runid);
288 #endif
289                 jbus_reply_error_s(smsg, error_system);
290         }
291         json_object_put(resp);
292         free(uri);
293 }
294
295 /*
296  * On query "once" from 'smsg' with parameters of 'obj'.
297  */
298 static void on_once(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
299 {
300         const char *appid;
301         struct json_object *appli, *resp;
302         int runid;
303
304         /* get the parameters */
305         if (!j_read_string(obj, &appid) && !j_read_string_at(obj, "id", &appid)) {
306                 jbus_reply_error_s(smsg, error_bad_request);
307                 return;
308         }
309
310         /* get the application */
311         INFO("method once called for %s", appid);
312 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
313         appli = afm_db_get_application(afdb, appid);
314 #else
315         appli = afm_udb_get_application_private(afudb, appid);
316 #endif
317         if (appli == NULL) {
318                 jbus_reply_error_s(smsg, error_not_found);
319                 return;
320         }
321
322         /* launch the application */
323 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
324         runid = afm_run_once(appli);
325 #else
326         runid = afm_urun_once(appli);
327 #endif
328         if (runid <= 0) {
329                 jbus_reply_error_s(smsg, error_cant_start);
330                 return;
331         }
332
333         /* returns the state */
334 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
335         resp = afm_run_state(runid);
336 #else
337         resp = afm_urun_state(afudb, runid);
338 #endif
339         reply(smsg, resp, error_not_found);
340         json_object_put(resp);
341 }
342
343 /*
344  * On query "pause" from 'smsg' with parameters of 'obj'.
345  */
346 static void on_pause(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
347 {
348         int runid, status;
349         if (onrunid(smsg, obj, "pause", &runid)) {
350 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
351                 status = afm_run_pause(runid);
352 #else
353                 status = afm_urun_pause(runid);
354 #endif
355                 reply_status(smsg, status, error_not_found);
356         }
357 }
358
359 /*
360  * On query "resume" from 'smsg' with parameters of 'obj'.
361  */
362 static void on_resume(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
363 {
364         int runid, status;
365         if (onrunid(smsg, obj, "resume", &runid)) {
366 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
367                 status = afm_run_resume(runid);
368 #else
369                 status = afm_urun_resume(runid);
370 #endif
371                 reply_status(smsg, status, error_not_found);
372         }
373 }
374
375 /*
376  * On query "stop" from 'smsg' with parameters of 'obj'.
377  */
378 static void on_stop(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
379 {
380         NOTICE("call to obsolete 'stop'");
381         on_pause(smsg, obj, unused);
382 }
383
384 /*
385  * On query "continue" from 'smsg' with parameters of 'obj'.
386  */
387 static void on_continue(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
388 {
389         NOTICE("call to obsolete 'continue'");
390         on_resume(smsg, obj, unused);
391 }
392
393 /*
394  * On query "terminate" from 'smsg' with parameters of 'obj'.
395  */
396 static void on_terminate(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
397 {
398         int runid, status;
399         if (onrunid(smsg, obj, "terminate", &runid)) {
400 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
401                 status = afm_run_terminate(runid);
402 #else
403                 status = afm_urun_terminate(runid);
404 #endif
405                 reply_status(smsg, status, error_not_found);
406         }
407 }
408
409 /*
410  * On query "runners" from 'smsg' with parameters of 'obj'.
411  */
412 static void on_runners(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
413 {
414         struct json_object *resp;
415         INFO("method runners called");
416 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
417         resp = afm_run_list();
418 #else
419         resp = afm_urun_list(afudb);
420 #endif
421         jbus_reply_j(smsg, resp);
422         json_object_put(resp);
423 }
424
425 /*
426  * On query "state" from 'smsg' with parameters of 'obj'.
427  */
428 static void on_state(struct sd_bus_message *smsg, struct json_object *obj, void *unused)
429 {
430         int runid;
431         struct json_object *resp;
432         if (onrunid(smsg, obj, "state", &runid)) {
433 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
434                 resp = afm_run_state(runid);
435 #else
436                 resp = afm_urun_state(afudb, runid);
437 #endif
438                 reply(smsg, resp, error_not_found);
439                 json_object_put(resp);
440         }
441 }
442
443 /*
444  * Calls the system daemon to achieve application management of
445  * the 'method' gotten from 'smsg' with the parameter's string 'msg'.
446  *
447  * The principle is very simple: call the corresponding system method
448  * and reply its response to the caller.
449  *
450  * The request and reply is synchronous and is blocking.
451  * It is possible to implment it in an asynchrounous way but it
452  * would brake the common behaviour. It would be a call like
453  * jbus_call_ss(system_bus, method, msg, callback, smsg)
454  */
455 static void propagate(struct sd_bus_message *smsg, const char *msg, const char *method)
456 {
457         char *reply;
458         INFO("method %s propagated with %s", method, msg);
459         reply = jbus_call_ss_sync(system_bus, method, msg);
460         if (reply) {
461                 jbus_reply_s(smsg, reply);
462                 free(reply);
463         }
464         else
465                 jbus_reply_error_s(smsg, error_system);
466 }
467
468 #if defined(EXPLICIT_CALL)
469 /*
470  * On query "install" from 'smsg' with parameters of 'msg'.
471  */
472 static void on_install(struct sd_bus_message *smsg, const char *msg, void *unused)
473 {
474         return propagate(smsg, msg, "install");
475 }
476
477 /*
478  * On query "uninstall" from 'smsg' with parameters of 'msg'.
479  */
480 static void on_uninstall(struct sd_bus_message *smsg, const char *msg, void *unused)
481 {
482         return propagate(smsg, msg, "uninstall");
483 }
484 #endif
485
486 /*
487  * On system signaling that applications list changed
488  */
489 static void on_signal_changed(struct json_object *obj, void *unused)
490 {
491 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
492         /* update the database */
493         afm_db_update_applications(afdb);
494 #else
495         /* enforce daemon reload */
496         systemd_daemon_reload(1);
497         systemd_unit_restart_name(1, "sockets.target");
498
499         /* update the database */
500         afm_udb_update(afudb);
501 #endif
502         /* re-propagate now */
503         jbus_send_signal_j(user_bus, "changed", obj);
504 }
505
506 /*
507  * Tiny routine to daemonize the program
508  * Return 0 on success or -1 on failure.
509  */
510 static int daemonize()
511 {
512         int rc = fork();
513         if (rc < 0)
514                 return rc;
515         if (rc)
516                 _exit(0);
517         return 0;
518 }
519
520 /*
521  * Opens a sd-bus connection and returns it in 'ret'.
522  * The sd-bus connexion is intended to be for user if 'isuser'
523  * is not null. The adress is the default address when 'address'
524  * is NULL or, otherwise, the given address.
525  * It might be necessary to pass the address as an argument because
526  * library systemd uses secure_getenv to retrieves the default
527  * addresses and secure_getenv might return NULL in some cases.
528  */
529 static int open_bus(sd_bus **ret, int isuser, const char *address)
530 {
531         sd_bus *b;
532         int rc;
533
534         if (address == NULL)
535                 return (isuser ? sd_bus_default_user : sd_bus_default_system)(ret);
536
537         rc = sd_bus_new(&b);
538         if (rc < 0)
539                 return rc;
540
541         rc = sd_bus_set_address(b, address);
542         if (rc < 0)
543                 goto fail;
544
545         sd_bus_set_bus_client(b, 1);
546
547         rc = sd_bus_start(b);
548         if (rc < 0)
549                 goto fail;
550
551         *ret = b;
552         return 0;
553
554 fail:
555         sd_bus_unref(b);
556         return rc;
557 }
558
559 /*
560  * ENTRY POINT OF AFM-USER-DAEMON
561  */
562 int main(int ac, char **av)
563 {
564         int i, daemon = 0, rc;
565 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
566         enum afm_launch_mode mode;
567 #endif
568         struct sd_event *evloop;
569         struct sd_bus *sysbus, *usrbus;
570         const char *sys_bus_addr, *usr_bus_addr;
571
572         LOGAUTH(appname);
573
574         /* first interpretation of arguments */
575         sys_bus_addr = NULL;
576         usr_bus_addr = NULL;
577         while ((i = getopt_long(ac, av, options_s, options_l, NULL)) >= 0) {
578                 switch (i) {
579                 case 'h':
580                         printf(usagestr, appname);
581                         return 0;
582                 case 'q':
583                         if (verbosity)
584                                 verbosity--;
585                         break;
586                 case 'v':
587                         verbosity++;
588                         break;
589                 case 'd':
590                         daemon = 1;
591                         break;
592 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
593                 case 'r':
594                         break;
595                 case 'a':
596                         break;
597                 case 'm':
598                         mode = launch_mode_of_name(optarg);
599                         if (!is_valid_launch_mode(mode)) {
600                                 ERROR("invalid mode '%s'", optarg);
601                                 return 1;
602                         }
603                         set_default_launch_mode(mode);
604                         break;
605 #endif
606                 case 'u':
607                         usr_bus_addr = optarg;
608                         break;
609                 case 's':
610                         sys_bus_addr = optarg;
611                         break;
612                 case ':':
613                         ERROR("missing argument value");
614                         return 1;
615                 default:
616                         ERROR("unrecognized option");
617                         return 1;
618                 }
619         }
620
621         /* init random generator */
622         srandom((unsigned int)time(NULL));
623
624 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
625         /* init runners */
626         if (afm_run_init()) {
627                 ERROR("afm_run_init failed");
628                 return 1;
629         }
630
631         /* init framework */
632         afdb = afm_db_create();
633         if (!afdb) {
634                 ERROR("afm_db_create failed");
635                 return 1;
636         }
637         if (afm_db_add_root(afdb, FWK_APP_DIR)) {
638                 ERROR("can't add root %s", FWK_APP_DIR);
639                 return 1;
640         }
641
642         /* second interpretation of arguments */
643         optind = 1;
644         while ((i = getopt_long(ac, av, options_s, options_l, NULL)) >= 0) {
645                 switch (i) {
646                 case 'r':
647                         if (afm_db_add_root(afdb, optarg)) {
648                                 ERROR("can't add root %s", optarg);
649                                 return 1;
650                         }
651                         break;
652                 case 'a':
653                         if (afm_db_add_application(afdb, optarg)) {
654                                 ERROR("can't add application %s", optarg);
655                                 return 1;
656                         }
657                         break;
658                 }
659         }
660
661         /* update the database */
662         if (afm_db_update_applications(afdb)) {
663                 ERROR("afm_update_applications failed");
664                 return 1;
665         }
666 #else
667         /* init database */
668         afudb = afm_udb_create(0, 1, "afm-appli-");
669         if (!afudb) {
670                 ERROR("afm_udb_create failed");
671                 return 1;
672         }
673 #endif
674
675         /* daemonize if requested */
676         if (daemon && daemonize()) {
677                 ERROR("daemonization failed");
678                 return 1;
679         }
680
681         /* get systemd objects */
682         rc = sd_event_new(&evloop);
683         if (rc < 0) {
684                 ERROR("can't create event loop");
685                 return 1;
686         }
687         rc = open_bus(&sysbus, 0, sys_bus_addr);
688         if (rc < 0) {
689                 ERROR("can't create system bus");
690                 return 1;
691         }
692         rc = sd_bus_attach_event(sysbus, evloop, 0);
693         if (rc < 0) {
694                 ERROR("can't attach system bus to event loop");
695                 return 1;
696         }
697         rc = open_bus(&usrbus, 1, usr_bus_addr);
698         if (rc < 0) {
699                 ERROR("can't create user bus");
700                 return 1;
701         }
702         rc = sd_bus_attach_event(usrbus, evloop, 0);
703         if (rc < 0) {
704                 ERROR("can't attach user bus to event loop");
705                 return 1;
706         }
707
708         /* connects to the system bus */
709         system_bus = create_jbus(sysbus, AFM_SYSTEM_DBUS_PATH);
710         if (!system_bus) {
711                 ERROR("create_jbus failed for system");
712                 return 1;
713         }
714
715         /* observe signals of system */
716         if(jbus_on_signal_j(system_bus, "changed", on_signal_changed, NULL)) {
717                 ERROR("adding signal observer failed");
718                 return 1;
719         }
720
721         /* connect to the session bus */
722         user_bus = create_jbus(usrbus, AFM_USER_DBUS_PATH);
723         if (!user_bus) {
724                 ERROR("create_jbus failed");
725                 return 1;
726         }
727
728         /* init services */
729         if (jbus_add_service_j(user_bus, "runnables", on_runnables, NULL)
730          || jbus_add_service_j(user_bus, "detail",    on_detail, NULL)
731          || jbus_add_service_j(user_bus, "start",     on_start, NULL)
732          || jbus_add_service_j(user_bus, "once",      on_once, NULL)
733          || jbus_add_service_j(user_bus, "terminate", on_terminate, NULL)
734          || jbus_add_service_j(user_bus, "pause",     on_pause, NULL)
735          || jbus_add_service_j(user_bus, "resume",    on_resume, NULL)
736          || jbus_add_service_j(user_bus, "stop",      on_stop, NULL)
737          || jbus_add_service_j(user_bus, "continue",  on_continue, NULL)
738          || jbus_add_service_j(user_bus, "runners",   on_runners, NULL)
739          || jbus_add_service_j(user_bus, "state",     on_state, NULL)
740 #if defined(EXPLICIT_CALL)
741          || jbus_add_service_s(user_bus, "install",   on_install, NULL)
742          || jbus_add_service_s(user_bus, "uninstall", on_uninstall, NULL)
743 #else
744          || jbus_add_service_s(user_bus, "install",   (void (*)(struct sd_bus_message *, const char *, void *))propagate, "install")
745          || jbus_add_service_s(user_bus, "uninstall", (void (*)(struct sd_bus_message *, const char *, void *))propagate, "uninstall")
746 #endif
747          ) {
748                 ERROR("adding services failed");
749                 return 1;
750         }
751
752         /* start servicing */
753         if (jbus_start_serving(user_bus) < 0) {
754                 ERROR("can't start server");
755                 return 1;
756         }
757
758         /* run until error */
759         for(;;)
760                 sd_event_run(evloop, (uint64_t)-1);
761         return 0;
762 }
763