Update version of tools
[src/app-framework-main.git] / src / afm-system-daemon.c
index 9cb9433..097913a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- Copyright 2015 IoT.bzh
+ Copyright 2015, 2016, 2017 IoT.bzh
 
  author: José Bollo <jose.bollo@iot.bzh>
 
 #include <getopt.h>
 #include <errno.h>
 
-#include <json.h>
+#include <systemd/sd-bus.h>
+#include <systemd/sd-event.h>
+#include <json-c/json.h>
 
 #include "verbose.h"
 #include "utils-jbus.h"
 #include "utils-json.h"
+#include "utils-systemd.h"
 #include "afm.h"
 #include "afm-db.h"
 #include "wgt-info.h"
 static const char appname[] = "afm-system-daemon";
 static const char *rootdir = NULL;
 
+static void version()
+{
+       printf(
+               "\n"
+               "  %s  version="AFM_VERSION"\n"
+               "\n"
+               "  Copyright (C) 2015, 2016, 2017 \"IoT.bzh\"\n"
+               "  AFB comes with ABSOLUTELY NO WARRANTY.\n"
+               "  Licence Apache 2\n"
+               "\n",
+               appname
+       );
+}
+
 static void usage()
 {
        printf(
@@ -45,6 +62,7 @@ static void usage()
                "   -d           run as a daemon\n"
                "   -q           quiet\n"
                "   -v           verbose\n"
+               "   -V           version\n"
                "\n",
                appname
        );
@@ -56,6 +74,7 @@ static struct option options[] = {
        { "quiet",       no_argument,       NULL, 'q' },
        { "verbose",     no_argument,       NULL, 'v' },
        { "help",        no_argument,       NULL, 'h' },
+       { "version",     no_argument,       NULL, 'V' },
        { NULL, 0, NULL, 0 }
 };
 
@@ -66,11 +85,21 @@ const char error_bad_request[] = "\"bad request\"";
 const char error_not_found[] = "\"not found\"";
 const char error_cant_start[] = "\"can't start\"";
 
-static void on_install(struct jreq *jreq, struct json_object *req)
+static void do_reloads()
+{
+#ifndef LEGACY_MODE_WITHOUT_SYSTEMD
+       /* enforce daemon reload */
+       systemd_daemon_reload(0);
+       systemd_unit_restart_name(0, "sockets.target");
+#endif
+}
+
+static void on_install(struct sd_bus_message *smsg, struct json_object *req, void *unused)
 {
        const char *wgtfile;
        const char *root;
        int force;
+       int reload;
        struct wgt_info *ifo;
        struct json_object *resp;
 
@@ -80,31 +109,38 @@ static void on_install(struct jreq *jreq, struct json_object *req)
                wgtfile = json_object_get_string(req);
                root = rootdir;
                force = 0;
+               reload = 1;
                break;
        case json_type_object:
                wgtfile = j_string_at(req, "wgt", NULL);
                if (wgtfile != NULL) {
                        root = j_string_at(req, "root", rootdir);
                        force = j_boolean_at(req, "force", 0);
+                       reload = j_boolean_at(req, "reload", 1);
                        break;
                }
+               /*@fallthrough@*/
        default:
-               jbus_reply_error_s(jreq, error_bad_request);
+               jbus_reply_error_s(smsg, error_bad_request);
                return;
        }
 
        /* install the widget */
        ifo = install_widget(wgtfile, root, force);
        if (ifo == NULL)
-               jbus_reply_error_s(jreq, "\"installation failed\"");
+               jbus_reply_error_s(smsg, "\"installation failed\"");
        else {
+               /* reload if needed */
+               if (reload)
+                       do_reloads();
+
                /* build the response */
                resp = json_object_new_object();
                if(!resp || !j_add_string(resp, "added", wgt_info_desc(ifo)->idaver))
-                       jbus_reply_error_s(jreq, "\"out of memory but installed!\"");
+                       jbus_reply_error_s(smsg, "\"out of memory but installed!\"");
                else {
                        jbus_send_signal_s(jbus, "changed", "true");
-                       jbus_reply_j(jreq, resp);
+                       jbus_reply_j(smsg, resp);
                }
 
                /* clean-up */
@@ -113,7 +149,7 @@ static void on_install(struct jreq *jreq, struct json_object *req)
        }
 }
 
-static void on_uninstall(struct jreq *jreq, struct json_object *req)
+static void on_uninstall(struct sd_bus_message *smsg, struct json_object *req, void *unused)
 {
        const char *idaver;
        const char *root;
@@ -131,18 +167,19 @@ static void on_uninstall(struct jreq *jreq, struct json_object *req)
                        root = j_string_at(req, "root", rootdir);
                        break;
                }
+               /*@fallthrough@*/
        default:
-               jbus_reply_error_s(jreq, error_bad_request);
+               jbus_reply_error_s(smsg, error_bad_request);
                return;
        }
 
        /* install the widget */
        rc = uninstall_widget(idaver, root);
        if (rc)
-               jbus_reply_error_s(jreq, "\"uninstallation had error\"");
+               jbus_reply_error_s(smsg, "\"uninstallation had error\"");
        else {
                jbus_send_signal_s(jbus, "changed", "true");
-               jbus_reply_s(jreq, "true");
+               jbus_reply_s(smsg, "true");
        }
 }
 
@@ -158,16 +195,21 @@ static int daemonize()
 
 int main(int ac, char **av)
 {
-       int i, daemon = 0;
+       int i, daemon = 0, rc;
+       struct sd_event *evloop;
+       struct sd_bus *sysbus;
 
        LOGAUTH(appname);
 
        /* interpretation of arguments */
-       while ((i = getopt_long(ac, av, "hdqvr:", options, NULL)) >= 0) {
+       while ((i = getopt_long(ac, av, "hdqvVr:", options, NULL)) >= 0) {
                switch (i) {
                case 'h':
                        usage();
                        return 0;
+               case 'V':
+                       version();
+                       return 0;
                case 'q':
                        if (verbosity)
                                verbosity--;
@@ -216,24 +258,41 @@ int main(int ac, char **av)
                return 1;
        }
 
+       /* get systemd objects */
+       rc = sd_event_new(&evloop);
+       if (rc < 0) {
+               ERROR("can't create event loop");
+               return 1;
+       }
+       rc = sd_bus_open_system(&sysbus);
+       if (rc < 0) {
+               ERROR("can't create system bus");
+               return 1;
+       }
+       rc = sd_bus_attach_event(sysbus, evloop, 0);
+       if (rc < 0) {
+               ERROR("can't attach system bus to event loop");
+               return 1;
+       }
+
        /* init service */
-       jbus = create_jbus(0, AFM_SYSTEM_DBUS_PATH);
+       jbus = create_jbus(sysbus, AFM_SYSTEM_DBUS_PATH);
        if (!jbus) {
                ERROR("create_jbus failed");
                return 1;
        }
-       if(jbus_add_service_j(jbus, "install", on_install)
-       || jbus_add_service_j(jbus, "uninstall", on_uninstall)) {
+       if(jbus_add_service_j(jbus, "install", on_install, NULL)
+       || jbus_add_service_j(jbus, "uninstall", on_uninstall, NULL)) {
                ERROR("adding services failed");
                return 1;
        }
 
        /* start and run */
-       if (jbus_start_serving(jbus)) {
+       if (jbus_start_serving(jbus) < 0) {
                ERROR("can't start server");
                return 1;
        }
-       while (!jbus_read_write_dispatch(jbus, -1));
+       for(;;)
+               sd_event_run(evloop, (uint64_t)-1);
        return 0;
 }
-