Fix socket (de)activation at (de)install
[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         /* enforce daemon reload */
492         systemd_daemon_reload(1);
493         systemd_unit_restart_name(1, "sockets.target");
494
495         /* update the database */
496 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
497         afm_db_update_applications(afdb);
498 #else
499         afm_udb_update(afudb);
500 #endif
501         /* re-propagate now */
502         jbus_send_signal_j(user_bus, "changed", obj);
503 }
504
505 /*
506  * Tiny routine to daemonize the program
507  * Return 0 on success or -1 on failure.
508  */
509 static int daemonize()
510 {
511         int rc = fork();
512         if (rc < 0)
513                 return rc;
514         if (rc)
515                 _exit(0);
516         return 0;
517 }
518
519 /*
520  * Opens a sd-bus connection and returns it in 'ret'.
521  * The sd-bus connexion is intended to be for user if 'isuser'
522  * is not null. The adress is the default address when 'address'
523  * is NULL or, otherwise, the given address.
524  * It might be necessary to pass the address as an argument because
525  * library systemd uses secure_getenv to retrieves the default
526  * addresses and secure_getenv might return NULL in some cases.
527  */
528 static int open_bus(sd_bus **ret, int isuser, const char *address)
529 {
530         sd_bus *b;
531         int rc;
532
533         if (address == NULL)
534                 return (isuser ? sd_bus_default_user : sd_bus_default_system)(ret);
535
536         rc = sd_bus_new(&b);
537         if (rc < 0)
538                 return rc;
539
540         rc = sd_bus_set_address(b, address);
541         if (rc < 0)
542                 goto fail;
543
544         sd_bus_set_bus_client(b, 1);
545
546         rc = sd_bus_start(b);
547         if (rc < 0)
548                 goto fail;
549
550         *ret = b;
551         return 0;
552
553 fail:
554         sd_bus_unref(b);
555         return rc;
556 }
557
558 /*
559  * ENTRY POINT OF AFM-USER-DAEMON
560  */
561 int main(int ac, char **av)
562 {
563         int i, daemon = 0, rc;
564 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
565         enum afm_launch_mode mode;
566 #endif
567         struct sd_event *evloop;
568         struct sd_bus *sysbus, *usrbus;
569         const char *sys_bus_addr, *usr_bus_addr;
570
571         LOGAUTH(appname);
572
573         /* first interpretation of arguments */
574         sys_bus_addr = NULL;
575         usr_bus_addr = NULL;
576         while ((i = getopt_long(ac, av, options_s, options_l, NULL)) >= 0) {
577                 switch (i) {
578                 case 'h':
579                         printf(usagestr, appname);
580                         return 0;
581                 case 'q':
582                         if (verbosity)
583                                 verbosity--;
584                         break;
585                 case 'v':
586                         verbosity++;
587                         break;
588                 case 'd':
589                         daemon = 1;
590                         break;
591 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
592                 case 'r':
593                         break;
594                 case 'a':
595                         break;
596                 case 'm':
597                         mode = launch_mode_of_name(optarg);
598                         if (!is_valid_launch_mode(mode)) {
599                                 ERROR("invalid mode '%s'", optarg);
600                                 return 1;
601                         }
602                         set_default_launch_mode(mode);
603                         break;
604 #endif
605                 case 'u':
606                         usr_bus_addr = optarg;
607                         break;
608                 case 's':
609                         sys_bus_addr = optarg;
610                         break;
611                 case ':':
612                         ERROR("missing argument value");
613                         return 1;
614                 default:
615                         ERROR("unrecognized option");
616                         return 1;
617                 }
618         }
619
620         /* init random generator */
621         srandom((unsigned int)time(NULL));
622
623 #ifdef LEGACY_MODE_WITHOUT_SYSTEMD
624         /* init runners */
625         if (afm_run_init()) {
626                 ERROR("afm_run_init failed");
627                 return 1;
628         }
629
630         /* init framework */
631         afdb = afm_db_create();
632         if (!afdb) {
633                 ERROR("afm_db_create failed");
634                 return 1;
635         }
636         if (afm_db_add_root(afdb, FWK_APP_DIR)) {
637                 ERROR("can't add root %s", FWK_APP_DIR);
638                 return 1;
639         }
640
641         /* second interpretation of arguments */
642         optind = 1;
643         while ((i = getopt_long(ac, av, options_s, options_l, NULL)) >= 0) {
644                 switch (i) {
645                 case 'r':
646                         if (afm_db_add_root(afdb, optarg)) {
647                                 ERROR("can't add root %s", optarg);
648                                 return 1;
649                         }
650                         break;
651                 case 'a':
652                         if (afm_db_add_application(afdb, optarg)) {
653                                 ERROR("can't add application %s", optarg);
654                                 return 1;
655                         }
656                         break;
657                 }
658         }
659
660         /* update the database */
661         if (afm_db_update_applications(afdb)) {
662                 ERROR("afm_update_applications failed");
663                 return 1;
664         }
665 #else
666         /* init database */
667         afudb = afm_udb_create(0, 1, "afm-appli-");
668         if (!afudb) {
669                 ERROR("afm_udb_create failed");
670                 return 1;
671         }
672 #endif
673
674         /* daemonize if requested */
675         if (daemon && daemonize()) {
676                 ERROR("daemonization failed");
677                 return 1;
678         }
679
680         /* get systemd objects */
681         rc = sd_event_new(&evloop);
682         if (rc < 0) {
683                 ERROR("can't create event loop");
684                 return 1;
685         }
686         rc = open_bus(&sysbus, 0, sys_bus_addr);
687         if (rc < 0) {
688                 ERROR("can't create system bus");
689                 return 1;
690         }
691         rc = sd_bus_attach_event(sysbus, evloop, 0);
692         if (rc < 0) {
693                 ERROR("can't attach system bus to event loop");
694                 return 1;
695         }
696         rc = open_bus(&usrbus, 1, usr_bus_addr);
697         if (rc < 0) {
698                 ERROR("can't create user bus");
699                 return 1;
700         }
701         rc = sd_bus_attach_event(usrbus, evloop, 0);
702         if (rc < 0) {
703                 ERROR("can't attach user bus to event loop");
704                 return 1;
705         }
706
707         /* connects to the system bus */
708         system_bus = create_jbus(sysbus, AFM_SYSTEM_DBUS_PATH);
709         if (!system_bus) {
710                 ERROR("create_jbus failed for system");
711                 return 1;
712         }
713
714         /* observe signals of system */
715         if(jbus_on_signal_j(system_bus, "changed", on_signal_changed, NULL)) {
716                 ERROR("adding signal observer failed");
717                 return 1;
718         }
719
720         /* connect to the session bus */
721         user_bus = create_jbus(usrbus, AFM_USER_DBUS_PATH);
722         if (!user_bus) {
723                 ERROR("create_jbus failed");
724                 return 1;
725         }
726
727         /* init services */
728         if (jbus_add_service_j(user_bus, "runnables", on_runnables, NULL)
729          || jbus_add_service_j(user_bus, "detail",    on_detail, NULL)
730          || jbus_add_service_j(user_bus, "start",     on_start, NULL)
731          || jbus_add_service_j(user_bus, "once",      on_once, NULL)
732          || jbus_add_service_j(user_bus, "terminate", on_terminate, NULL)
733          || jbus_add_service_j(user_bus, "pause",     on_pause, NULL)
734          || jbus_add_service_j(user_bus, "resume",    on_resume, NULL)
735          || jbus_add_service_j(user_bus, "stop",      on_stop, NULL)
736          || jbus_add_service_j(user_bus, "continue",  on_continue, NULL)
737          || jbus_add_service_j(user_bus, "runners",   on_runners, NULL)
738          || jbus_add_service_j(user_bus, "state",     on_state, NULL)
739 #if defined(EXPLICIT_CALL)
740          || jbus_add_service_s(user_bus, "install",   on_install, NULL)
741          || jbus_add_service_s(user_bus, "uninstall", on_uninstall, NULL)
742 #else
743          || jbus_add_service_s(user_bus, "install",   (void (*)(struct sd_bus_message *, const char *, void *))propagate, "install")
744          || jbus_add_service_s(user_bus, "uninstall", (void (*)(struct sd_bus_message *, const char *, void *))propagate, "uninstall")
745 #endif
746          ) {
747                 ERROR("adding services failed");
748                 return 1;
749         }
750
751         /* start servicing */
752         if (jbus_start_serving(user_bus) < 0) {
753                 ERROR("can't start server");
754                 return 1;
755         }
756
757         /* run until error */
758         for(;;)
759                 sd_event_run(evloop, (uint64_t)-1);
760         return 0;
761 }
762