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