Adding uninstallation of widgets
[src/app-framework-main.git] / src / afm-system-daemon.c
1 /*
2  Copyright 2015 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 <errno.h>
24
25 #include <json.h>
26
27 #include "verbose.h"
28 #include "utils-jbus.h"
29 #include "utils-json.h"
30 #include "afm.h"
31 #include "afm-db.h"
32 #include "wgt-info.h"
33 #include "wgtpkg-install.h"
34 #include "wgtpkg-uninstall.h"
35
36 static const char appname[] = "afm-system-daemon";
37 static const char *rootdir = NULL;
38
39 static void usage()
40 {
41         printf(
42                 "usage: %s [-q] [-v] [-r rootdir]\n"
43                 "\n"
44                 "   -r rootdir   set root directory of applications\n"
45                 "   -d           run as a daemon\n"
46                 "   -q           quiet\n"
47                 "   -v           verbose\n"
48                 "\n",
49                 appname
50         );
51 }
52
53 static struct option options[] = {
54         { "root",        required_argument, NULL, 'r' },
55         { "daemon",      no_argument,       NULL, 'd' },
56         { "quiet",       no_argument,       NULL, 'q' },
57         { "verbose",     no_argument,       NULL, 'v' },
58         { "help",        no_argument,       NULL, 'h' },
59         { NULL, 0, NULL, 0 }
60 };
61
62 static struct jbus *jbus;
63
64 const char error_nothing[] = "[]";
65 const char error_bad_request[] = "\"bad request\"";
66 const char error_not_found[] = "\"not found\"";
67 const char error_cant_start[] = "\"can't start\"";
68
69 static void on_install(struct jreq *jreq, struct json_object *req)
70 {
71         const char *wgtfile;
72         const char *root;
73         int force;
74         struct wgt_info *ifo;
75         struct json_object *resp;
76
77         /* scan the request */
78         switch (json_object_get_type(req)) {
79         case json_type_string:
80                 wgtfile = json_object_get_string(req);
81                 root = rootdir;
82                 force = 0;
83                 break;
84         case json_type_object:
85                 wgtfile = j_get_string(req, "wgt", NULL);
86                 if (wgtfile != NULL) {
87                         root = j_get_string(req, "root", rootdir);
88                         force = j_get_boolean(req, "force", 0);
89                         break;
90                 }
91         default:
92                 jbus_reply_error_s(jreq, error_bad_request);
93                 return;
94         }
95
96         /* install the widget */
97         ifo = install_widget(wgtfile, root, force);
98         if (ifo == NULL) {
99                 jbus_reply_error_s(jreq, "\"installation failed\"");
100                 return;
101         }
102
103         /* build the response */
104         resp = json_object_new_object();
105         if(!resp || !j_add_string(resp, "added", wgt_info_desc(ifo)->idaver)) {
106                 json_object_put(resp);
107                 wgt_info_unref(ifo);
108                 jbus_reply_error_s(jreq, "\"out of memory but installed!\"");
109                 return;
110         }
111         wgt_info_unref(ifo);
112
113         /* reply and propagate event */
114         jbus_reply_j(jreq, resp);
115         jbus_send_signal_j(jbus, "changed", resp);
116         json_object_put(resp);
117 }
118
119 static void on_uninstall(struct jreq *jreq, struct json_object *req)
120 {
121         const char *idaver;
122         const char *root;
123         int rc;
124
125         /* scan the request */
126         switch (json_object_get_type(req)) {
127         case json_type_string:
128                 idaver = json_object_get_string(req);
129                 root = rootdir;
130                 break;
131         case json_type_object:
132                 idaver = j_get_string(req, "id", NULL);
133                 if (idaver != NULL) {
134                         root = j_get_string(req, "root", rootdir);
135                         break;
136                 }
137         default:
138                 jbus_reply_error_s(jreq, error_bad_request);
139                 return;
140         }
141
142         /* install the widget */
143         rc = uninstall_widget(idaver, root);
144         if (rc) {
145                 jbus_reply_error_s(jreq, "\"uninstallation had error\"");
146                 return;
147         }
148         jbus_reply_s(jreq, "true");
149 }
150
151 static int daemonize()
152 {
153         int rc = fork();
154         if (rc < 0)
155                 return rc;
156         if (rc)
157                 _exit(0);
158         return 0;
159 }
160
161 int main(int ac, char **av)
162 {
163         int i, daemon = 0;
164
165         LOGAUTH(appname);
166
167         /* interpretation of arguments */
168         while ((i = getopt_long(ac, av, "hdqvr:", options, NULL)) >= 0) {
169                 switch (i) {
170                 case 'h':
171                         usage();
172                         return 0;
173                 case 'q':
174                         if (verbosity)
175                                 verbosity--;
176                         break;
177                 case 'v':
178                         verbosity++;
179                         break;
180                 case 'd':
181                         daemon = 1;
182                         break;
183                 case 'r':
184                         if (rootdir == NULL)
185                                 rootdir = optarg;
186                         else {
187                                 ERROR("duplicate definition of rootdir");
188                                 return 1;
189                         }
190                         break;
191                 case ':':
192                         ERROR("missing argument value");
193                         return 1;
194                 default:
195                         ERROR("unrecognized option");
196                         return 1;
197                 }
198         }
199
200         /* check the rootdir */
201         if (rootdir == NULL)
202                 rootdir = FWK_APP_DIR;
203         else {
204                 rootdir = realpath(rootdir, NULL);
205                 if (rootdir == NULL) {
206                         ERROR("out of memory");
207                         return 1;
208                 }
209         }
210         if (chdir(rootdir)) {
211                 ERROR("can't enter %s", rootdir);
212                 return 1;
213         }
214
215         /* daemonize */
216         if (daemon && daemonize()) {
217                 ERROR("daemonization failed");
218                 return 1;
219         }
220
221         /* init service */
222         jbus = create_jbus(0, AFM_SYSTEM_DBUS_PATH);
223         if (!jbus) {
224                 ERROR("create_jbus failed");
225                 return 1;
226         }
227         if(jbus_add_service_j(jbus, "install", on_install)
228         || jbus_add_service_j(jbus, "uninstall", on_uninstall)) {
229                 ERROR("adding services failed");
230                 return 1;
231         }
232
233         /* start and run */
234         if (jbus_start_serving(jbus)) {
235                 ERROR("can't start server");
236                 return 1;
237         }
238         while (!jbus_read_write_dispatch(jbus, -1));
239         return 0;
240 }
241