4 author: José Bollo <jose.bollo@iot.bzh>
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
10 http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include "utils-jbus.h"
32 static const char appname[] = "afm-user-daemon";
37 "usage: %s [-q] [-v] [-r rootdir]... [-a appdir]...\n"
39 " -a appdir adds an application directory\n"
40 " -r rootdir adds a root directory of applications\n"
41 " -d run as a daemon\n"
49 static struct option options[] = {
50 { "root", required_argument, NULL, 'r' },
51 { "application", required_argument, NULL, 'a' },
52 { "daemon", no_argument, NULL, 'd' },
53 { "quiet", no_argument, NULL, 'q' },
54 { "verbose", no_argument, NULL, 'v' },
55 { "help", no_argument, NULL, 'h' },
59 static struct jbus *jbuses[2];
60 static struct afm_db *afdb;
62 const char error_nothing[] = "[]";
63 const char error_bad_request[] = "\"bad request\"";
64 const char error_not_found[] = "\"not found\"";
65 const char error_cant_start[] = "\"can't start\"";
66 const char error_system[] = "\"system error\"";
68 static const char *getappid(struct json_object *obj)
70 return json_type_string == json_object_get_type(obj) ? json_object_get_string(obj) : NULL;
73 static int getrunid(struct json_object *obj)
75 return json_type_int == json_object_get_type(obj) ? json_object_get_int(obj) : 0;
78 static void reply(struct jreq *jreq, struct json_object *resp, const char *errstr)
81 jbus_reply_j(jreq, resp);
83 jbus_reply_error_s(jreq, errstr);
86 static void reply_status(struct jreq *jreq, int status)
89 jbus_reply_error_s(jreq, error_not_found);
91 jbus_reply_s(jreq, "true");
94 static void on_runnables(struct jreq *jreq, struct json_object *obj)
96 struct json_object *resp;
97 INFO("method runnables called");
98 resp = afm_db_application_list(afdb);
99 jbus_reply_j(jreq, resp);
100 json_object_put(resp);
103 static void on_detail(struct jreq *jreq, struct json_object *obj)
106 struct json_object *resp;
107 appid = getappid(obj);
108 INFO("method detail called for %s", appid);
109 resp = afm_db_get_application_public(afdb, appid);
110 reply(jreq, resp, error_not_found);
111 json_object_put(resp);
114 static void on_start(struct jreq *jreq, struct json_object *obj)
117 struct json_object *appli;
121 appid = getappid(obj);
122 INFO("method start called for %s", appid);
124 jbus_reply_error_s(jreq, error_bad_request);
126 appli = afm_db_get_application(afdb, appid);
128 jbus_reply_error_s(jreq, error_not_found);
130 runid = afm_run_start(appli);
132 jbus_reply_error_s(jreq, error_cant_start);
134 snprintf(runidstr, sizeof runidstr, "%d", runid);
135 runidstr[sizeof runidstr - 1] = 0;
136 jbus_reply_s(jreq, runidstr);
142 static void on_stop(struct jreq *jreq, struct json_object *obj)
145 runid = getrunid(obj);
146 INFO("method stop called for %d", runid);
147 status = afm_run_stop(runid);
148 reply_status(jreq, status);
151 static void on_continue(struct jreq *jreq, struct json_object *obj)
154 runid = getrunid(obj);
155 INFO("method continue called for %d", runid);
156 status = afm_run_continue(runid);
157 reply_status(jreq, status);
160 static void on_terminate(struct jreq *jreq, struct json_object *obj)
163 runid = getrunid(obj);
164 INFO("method terminate called for %d", runid);
165 status = afm_run_terminate(runid);
166 reply_status(jreq, status);
169 static void on_runners(struct jreq *jreq, struct json_object *obj)
171 struct json_object *resp;
172 INFO("method runners called");
173 resp = afm_run_list();
174 jbus_reply_j(jreq, resp);
175 json_object_put(resp);
178 static void on_state(struct jreq *jreq, struct json_object *obj)
181 struct json_object *resp;
182 runid = getrunid(obj);
183 INFO("method state called for %d", runid);
184 resp = afm_run_state(runid);
185 reply(jreq, resp, error_not_found);
186 json_object_put(resp);
189 static void propagate(struct jreq *jreq, const char *msg, const char *method)
192 INFO("method %s propagated with %s", method, msg);
193 reply = jbus_call_ss_sync(jbuses[0], method, msg);
195 jbus_reply_s(jreq, reply);
199 jbus_reply_error_s(jreq, error_system);
202 static void on_install(struct jreq *jreq, const char *msg)
204 return propagate(jreq, msg, "install");
207 static void on_uninstall(struct jreq *jreq, const char *msg)
209 return propagate(jreq, msg, "uninstall");
212 static void on_signal_changed(struct json_object *obj)
214 /* update the database */
215 afm_db_update_applications(afdb);
216 /* re-propagate now */
217 jbus_send_signal_j(jbuses[1], "changed", obj);
220 static int daemonize()
230 int main(int ac, char **av)
236 /* first interpretation of arguments */
237 while ((i = getopt_long(ac, av, "hdqvr:a:", options, NULL)) >= 0) {
257 ERROR("missing argument value");
260 ERROR("unrecognized option");
265 /* init random generator */
266 srandom((unsigned int)time(NULL));
269 if (afm_run_init()) {
270 ERROR("afm_run_init failed");
275 afdb = afm_db_create();
277 ERROR("afm_create failed");
280 if (afm_db_add_root(afdb, FWK_APP_DIR)) {
281 ERROR("can't add root %s", FWK_APP_DIR);
285 /* second interpretation of arguments */
287 while ((i = getopt_long(ac, av, "hdqvr:a:", options, NULL)) >= 0) {
290 if (afm_db_add_root(afdb, optarg)) {
291 ERROR("can't add root %s", optarg);
296 if (afm_db_add_application(afdb, optarg)) {
297 ERROR("can't add application %s", optarg);
304 /* update the database */
305 if (afm_db_update_applications(afdb)) {
306 ERROR("afm_update_applications failed");
310 if (daemon && daemonize()) {
311 ERROR("daemonization failed");
316 jbuses[0] = create_jbus(0, AFM_SYSTEM_DBUS_PATH);
318 ERROR("create_jbus failed for system");
321 if(jbus_on_signal_j(jbuses[0], "changed", on_signal_changed)) {
322 ERROR("adding signal observer failed");
327 jbuses[1] = create_jbus(1, AFM_USER_DBUS_PATH);
329 ERROR("create_jbus failed");
332 if(jbus_add_service_j(jbuses[1], "runnables", on_runnables)
333 || jbus_add_service_j(jbuses[1], "detail", on_detail)
334 || jbus_add_service_j(jbuses[1], "start", on_start)
335 || jbus_add_service_j(jbuses[1], "terminate", on_terminate)
336 || jbus_add_service_j(jbuses[1], "stop", on_stop)
337 || jbus_add_service_j(jbuses[1], "continue", on_continue)
338 || jbus_add_service_j(jbuses[1], "runners", on_runners)
339 || jbus_add_service_j(jbuses[1], "state", on_state)
340 || jbus_add_service_s(jbuses[1], "install", on_install)
341 || jbus_add_service_s(jbuses[1], "uninstall", on_uninstall)) {
342 ERROR("adding services failed");
347 if (jbus_start_serving(jbuses[1])) {
348 ERROR("can't start server");
351 while (jbus_read_write_dispatch_multiple(jbuses, 2, -1, 20) >= 0);