refactoring and moving forward
[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
24 #include <json.h>
25
26 #include "verbose.h"
27 #include "utils-jbus.h"
28 #include "afm.h"
29 #include "afm-db.h"
30
31 static const char appname[] = "afm-system-daemon";
32
33 static void usage()
34 {
35         printf(
36                 "usage: %s [-q] [-v] [-r rootdir]... [-a appdir]...\n"
37                 "\n"
38                 "   -a appdir    adds an application directory\n"
39                 "   -r rootdir   adds a root directory of applications\n"
40                 "   -d           run as a daemon\n"
41                 "   -q           quiet\n"
42                 "   -v           verbose\n"
43                 "\n",
44                 appname
45         );
46 }
47
48 static struct option options[] = {
49         { "root",        required_argument, NULL, 'r' },
50         { "application", required_argument, NULL, 'a' },
51         { "daemon",      no_argument,       NULL, 'd' },
52         { "quiet",       no_argument,       NULL, 'q' },
53         { "verbose",     no_argument,       NULL, 'v' },
54         { "help",        no_argument,       NULL, 'h' },
55         { NULL, 0, NULL, 0 }
56 };
57
58 static struct jbus *jbus;
59 static struct afm_db *afdb;
60
61 const char error_nothing[] = "[]";
62 const char error_bad_request[] = "\"bad request\"";
63 const char error_not_found[] = "\"not found\"";
64 const char error_cant_start[] = "\"can't start\"";
65
66 static const char *getappid(struct json_object *obj)
67 {
68         return json_type_string == json_object_get_type(obj) ? json_object_get_string(obj) : NULL;
69 }
70
71 static void reply(struct jreq *jreq, struct json_object *resp, const char *errstr)
72 {
73         if (resp)
74                 jbus_reply_j(jreq, resp);
75         else
76                 jbus_reply_error_s(jreq, errstr);
77 }
78
79 static void on_runnables(struct jreq *jreq, struct json_object *obj)
80 {
81         struct json_object *resp = afm_db_application_list(afdb);
82         jbus_reply_j(jreq, resp);
83         json_object_put(resp);
84 }
85
86 static void on_detail(struct jreq *jreq, struct json_object *obj)
87 {
88         const char *appid = getappid(obj);
89         struct json_object *resp = afm_db_get_application_public(afdb, appid);
90         reply(jreq, resp, error_not_found);
91         json_object_put(resp);
92 }
93
94 extern void install_widget(const char *wgtfile, const char *root, int force);
95 static void on_install(struct jreq *jreq, struct json_object *obj)
96 {
97         jbus_reply_error_s(jreq, "\"not yet implemented\"");
98 }
99
100 static void on_uninstall(struct jreq *jreq, struct json_object *obj)
101 {
102         jbus_reply_error_s(jreq, "\"not yet implemented\"");
103 }
104
105 static int daemonize()
106 {
107         int rc = fork();
108         if (rc < 0)
109                 return rc;
110         if (rc)
111                 _exit(0);
112         return 0;
113 }
114
115 int main(int ac, char **av)
116 {
117         int i, daemon = 0;
118
119         LOGAUTH(appname);
120
121         /* first interpretation of arguments */
122         while ((i = getopt_long(ac, av, "hdqvr:a:", options, NULL)) >= 0) {
123                 switch (i) {
124                 case 'h':
125                         usage();
126                         return 0;
127                 case 'q':
128                         if (verbosity)
129                                 verbosity--;
130                         break;
131                 case 'v':
132                         verbosity++;
133                         break;
134                 case 'd':
135                         daemon = 1;
136                         break;
137                 case 'r':
138                         break;
139                 case 'a':
140                         break;
141                 case ':':
142                         ERROR("missing argument value");
143                         return 1;
144                 default:
145                         ERROR("unrecognized option");
146                         return 1;
147                 }
148         }
149
150         /* init framework */
151         afdb = afm_db_create();
152         if (!afdb) {
153                 ERROR("afm_create failed");
154                 return 1;
155         }
156         if (afm_db_add_root(afdb, FWK_APP_DIR)) {
157                 ERROR("can't add root %s", FWK_APP_DIR);
158                 return 1;
159         }
160
161         /* second interpretation of arguments */
162         optind = 1;
163         while ((i = getopt_long(ac, av, "hdqvr:a:", options, NULL)) >= 0) {
164                 switch (i) {
165                 case 'r':
166                         if (afm_db_add_root(afdb, optarg)) {
167                                 ERROR("can't add root %s", optarg);
168                                 return 1;
169                         }
170                         break;
171                 case 'a':
172                         if (afm_db_add_application(afdb, optarg)) {
173                                 ERROR("can't add application %s", optarg);
174                                 return 1;
175                         }
176                         break;
177                 }
178         }
179
180         /* update the database */
181         if (afm_db_update_applications(afdb)) {
182                 ERROR("afm_update_applications failed");
183                 return 1;
184         }
185
186         if (daemon && daemonize()) {
187                 ERROR("daemonization failed");
188                 return 1;
189         }
190
191         /* init service */
192         jbus = create_jbus(0, AFM_SYSTEM_DBUS_PATH);
193         if (!jbus) {
194                 ERROR("create_jbus failed");
195                 return 1;
196         }
197         if(jbus_add_service_j(jbus, "runnables", on_runnables)
198         || jbus_add_service_j(jbus, "detail", on_detail)
199         || 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("cant start server");
208                 return 1;
209         }
210         while (!jbus_read_write_dispatch(jbus, -1));
211         return 0;
212 }
213