Update SMACK, Fix a crash of terminating sequence, etc, ...
[apps/livebox/data-provider-master.git] / src / conf.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <Ecore_X.h>
18 #include <ctype.h>
19
20 #include <dlog.h>
21 #include <livebox-errno.h>
22
23 #include "conf.h"
24 #include "util.h"
25 #include "debug.h"
26
27 HAPI struct conf g_conf = {
28         .width = 0,
29         .height = 0,
30
31         .base_width = 720,
32         .base_height = 1280,
33
34         .minimum_period = 1.0f,
35
36         .default_conf.script = "edje",
37         .default_conf.abi = "c",
38         .default_conf.pd_group = "disclosure",
39         .default_conf.period = -1.0f,
40
41         .launch_key.name = "name",
42         .launch_key.secured = "secured",
43         .launch_key.abi = "abi",
44
45         .default_packet_time = 0.0001f,
46
47         .empty_content = "",
48         .empty_title = "",
49
50         .default_content = "default",
51         .default_title = "",
52
53         .minimum_space = 5242880,
54
55         .replace_tag = "/APPID/",
56
57         .slave_ttl = 30.0f,
58         .slave_activate_time = 30.0f,
59
60         .max_log_line = 1000,
61         .max_log_file = 3,
62
63         .sqlite_flush_max = 1048576,
64
65         .path = {
66                 .conf = "/opt/usr/live/%s/etc/%s.conf",
67                 .image = "/opt/usr/share/live_magazine/",
68                 .slave_log = "/opt/usr/share/live_magazine/log",
69                 .reader = "/opt/usr/share/live_magazine/reader",
70                 .always = "/opt/usr/share/live_magazine/always",
71                 .script = "/opt/usr/live/%s/res/script/%s.edj",
72                 .root = "/opt/usr/live/",
73                 .script_port = "/usr/share/data-provider-master/plugin-script/",
74                 .db = "/opt/dbspace/.livebox.db",
75                 .input = "/dev/input/event1",
76         },
77
78         .ping_time = 240.0f,
79         .slave_max_load = 30,
80
81         .use_sw_backend = 0,
82         .provider_method = "pixmap",
83         .debug_mode = 0,
84         .overwrite_content = 0,
85         .com_core_thread = 1,
86         .use_xmonitor = 0,
87
88         .scale_width_factor = 1.0f,
89         .scale_height_factor = 1.0f,
90         .pd_request_timeout = 5.0f,
91 };
92
93 static void conf_update_size(void)
94 {
95         ecore_x_window_size_get(0, &g_conf.width, &g_conf.height);
96         g_conf.scale_width_factor = (double)g_conf.width / (double)BASE_W;
97         g_conf.scale_height_factor = (double)g_conf.height / (double)BASE_H;
98 }
99
100 static void use_xmonitor(char *buffer)
101 {
102         g_conf.use_xmonitor = !strcasecmp(buffer, "true");
103         DbgPrint("Use xmonitor: %d\n", g_conf.use_xmonitor);
104 }
105
106 static void use_sw_backend_handler(char *buffer)
107 {
108         g_conf.use_sw_backend = !strcasecmp(buffer, "true");
109         DbgPrint("SW Backend: %d\n", g_conf.use_sw_backend);
110 }
111
112 static void provider_method_handler(char *buffer)
113 {
114         g_conf.provider_method = strdup(buffer);
115         if (!g_conf.provider_method)
116                 ErrPrint("Heap: %s\n", strerror(errno));
117
118         DbgPrint("Method: %s\n", g_conf.provider_method);
119 }
120
121 static void debug_mode_handler(char *buffer)
122 {
123         g_conf.debug_mode = !strcasecmp(buffer, "true");
124         DbgPrint("Debug mode: %d\n", g_conf.debug_mode);
125 }
126
127 static void overwrite_content_handler(char *buffer)
128 {
129         g_conf.overwrite_content = !strcasecmp(buffer, "true");
130         DbgPrint("Overwrite Content: %d\n", g_conf.overwrite_content);
131 }
132
133 static void com_core_thread_handler(char *buffer)
134 {
135         g_conf.com_core_thread = !strcasecmp(buffer, "true");
136         DbgPrint("Com core thread: %d\n", g_conf.com_core_thread);
137 }
138
139 static void base_width_handler(char *buffer)
140 {
141         if (sscanf(buffer, "%d", &g_conf.base_width) != 1)
142                 ErrPrint("Failed to parse the base_width\n");
143
144         DbgPrint("Base width: %d\n", g_conf.base_width);
145 }
146
147 static void base_height_handler(char *buffer)
148 {
149         if (sscanf(buffer, "%d", &g_conf.base_height) != 1)
150                 ErrPrint("Failed to parse the base_height\n");
151         DbgPrint("Base height: %d\n", g_conf.base_height);
152 }
153
154 static void minimum_period_handler(char *buffer)
155 {
156         if (sscanf(buffer, "%lf", &g_conf.minimum_period) != 1)
157                 ErrPrint("Failed to parse the minimum_period\n");
158         DbgPrint("Minimum period: %lf\n", g_conf.minimum_period);
159 }
160
161 static void script_handler(char *buffer)
162 {
163         g_conf.default_conf.script = strdup(buffer);
164         if (!g_conf.default_conf.script)
165                 ErrPrint("Heap: %s\n", strerror(errno));
166         DbgPrint("Default script: %s\n", g_conf.default_conf.script);
167 }
168
169 static void default_abi_handler(char *buffer)
170 {
171         g_conf.default_conf.abi = strdup(buffer);
172         if (!g_conf.default_conf.abi)
173                 ErrPrint("Heap: %s\n", strerror(errno));
174         DbgPrint("Default ABI: %s\n", g_conf.default_conf.abi);
175 }
176
177 static void default_group_handler(char *buffer)
178 {
179         g_conf.default_conf.pd_group = strdup(buffer);
180         if (!g_conf.default_conf.pd_group)
181                 ErrPrint("Heap: %s\n", strerror(errno));
182         DbgPrint("Default PD Group: %s\n", g_conf.default_conf.pd_group);
183 }
184
185 static void default_period_handler(char *buffer)
186 {
187         if (sscanf(buffer, "%lf", &g_conf.default_conf.period) != 1)
188                 ErrPrint("Failed to parse the default_period\n");
189         DbgPrint("Default Period: %lf\n", g_conf.default_conf.period);
190 }
191
192 static void default_packet_time_handler(char *buffer)
193 {
194         if (sscanf(buffer, "%lf", &g_conf.default_packet_time) != 1)
195                 ErrPrint("Failed to parse the default_packet_time\n");
196         DbgPrint("Default packet time: %lf\n", g_conf.default_packet_time);
197 }
198
199 static void default_content_handler(char *buffer)
200 {
201         g_conf.default_content = strdup(buffer);
202         if (!g_conf.default_content)
203                 ErrPrint("Heap: %s\n", strerror(errno));
204         DbgPrint("Default content: %s\n", g_conf.default_content);
205 }
206
207 static void default_title_handler(char *buffer)
208 {
209         g_conf.default_title = strdup(buffer);
210         if (!g_conf.default_title)
211                 ErrPrint("Heap: %s\n", strerror(errno));
212         DbgPrint("Default title: %s\n", g_conf.default_title);
213 }
214
215 static void minimum_space_handler(char *buffer)
216 {
217         if (sscanf(buffer, "%lu", &g_conf.minimum_space) != 1)
218                 ErrPrint("Failed to parse the minimum_space\n");
219         DbgPrint("Minimum space: %lu\n", g_conf.minimum_space);
220 }
221
222 static void replace_tag_handler(char *buffer)
223 {
224         g_conf.replace_tag = strdup(buffer);
225         if (!g_conf.replace_tag)
226                 ErrPrint("Heap: %s\n", strerror(errno));
227         DbgPrint("Replace Tag: %s\n", g_conf.replace_tag);
228 }
229
230 static void slave_ttl_handler(char *buffer)
231 {
232         if (sscanf(buffer, "%lf", &g_conf.slave_ttl) != 1)
233                 ErrPrint("Failed to parse the slave_ttl\n");
234         DbgPrint("Slave TTL: %lf\n", g_conf.slave_ttl);
235 }
236
237 static void slave_activate_time_handler(char *buffer)
238 {
239         if (sscanf(buffer, "%lf", &g_conf.slave_activate_time) != 1)
240                 ErrPrint("Failed to parse the slave_activate_time\n");
241         DbgPrint("Slave activate time: %lf\n", g_conf.slave_activate_time);
242 }
243
244 static void max_log_line_handler(char *buffer)
245 {
246         if (sscanf(buffer, "%d", &g_conf.max_log_line) != 1)
247                 ErrPrint("Failed to parse the max_log_line\n");
248         DbgPrint("Max log line: %d\n", g_conf.max_log_line);
249 }
250
251 static void max_log_file_handler(char *buffer)
252 {
253         if (sscanf(buffer, "%d", &g_conf.max_log_file) != 1)
254                 ErrPrint("Failed to parse the max_log_file\n");
255         DbgPrint("Max log file: %d\n", g_conf.max_log_file);
256 }
257
258 static void sqlite_flush_max_handler(char *buffer)
259 {
260         if (sscanf(buffer, "%lu", &g_conf.sqlite_flush_max) != 1)
261                 ErrPrint("Failed to parse the sqlite_flush_max\n");
262         DbgPrint("Flush size: %lu\n", g_conf.sqlite_flush_max);
263 }
264
265 static void db_path_handler(char *buffer)
266 {
267         g_conf.path.db = strdup(buffer);
268         if (!g_conf.path.db)
269                 ErrPrint("Heap: %s\n", strerror(errno));
270         DbgPrint("DB Path: %s\n", g_conf.path.db);
271 }
272
273 static void reader_path_handler(char *buffer)
274 {
275         g_conf.path.reader = strdup(buffer);
276         if (!g_conf.path.reader)
277                 ErrPrint("Heap: %s\n", strerror(errno));
278         DbgPrint("Reader Path: %s\n", g_conf.path.reader);
279 }
280
281 static void always_path_handler(char *buffer)
282 {
283         g_conf.path.always = strdup(buffer);
284         if (!g_conf.path.always)
285                 ErrPrint("Heap: %s\n", strerror(errno));
286         DbgPrint("Always Path: %s\n", g_conf.path.always);
287 }
288
289 static void log_path_handler(char *buffer)
290 {
291         g_conf.path.slave_log = strdup(buffer);
292         if (!g_conf.path.slave_log)
293                 ErrPrint("Heap: %s\n", strerror(errno));
294         DbgPrint("LOG Path: %s\n", g_conf.path.slave_log);
295 }
296
297 static void script_port_path_handler(char *buffer)
298 {
299         g_conf.path.script_port = strdup(buffer);
300         if (!g_conf.path.script_port)
301                 ErrPrint("Heap: %s\n", strerror(errno));
302         DbgPrint("Script Port PATH: %s\n", g_conf.path.script_port);
303 }
304
305 static void share_path_handler(char *buffer)
306 {
307         g_conf.path.image = strdup(buffer);
308         if (!g_conf.path.image)
309                 ErrPrint("Heap: %s\n", strerror(errno));
310         DbgPrint("Shared folder: %s\n", g_conf.path.image);
311 }
312
313 static void input_path_handler(char *buffer)
314 {
315         g_conf.path.input = strdup(buffer);
316         if (!g_conf.path.input)
317                 ErrPrint("Heap: %s\n", strerror(errno));
318         DbgPrint("Input device: %s\n", g_conf.path.input);
319 }
320
321 static void ping_time_handler(char *buffer)
322 {
323         if (sscanf(buffer, "%lf", &g_conf.ping_time) != 1)
324                 ErrPrint("Failed to parse the ping_time\n");
325         DbgPrint("Default ping time: %lf\n", g_conf.ping_time);
326 }
327
328 static void slave_max_loader(char *buffer)
329 {
330         if (sscanf(buffer, "%d", &g_conf.slave_max_load) != 1)
331                 ErrPrint("Failed to parse the slave_max_load\n");
332         DbgPrint("Max load: %d\n", g_conf.slave_max_load);
333 }
334
335 static void pd_request_timeout_handler(char *buffer)
336 {
337         if (sscanf(buffer, "%lf", &g_conf.pd_request_timeout) != 1)
338                 ErrPrint("Failed to parse the request_timeout\n");
339         DbgPrint("Default PD request timeout: %lf\n", g_conf.pd_request_timeout);
340 }
341
342 HAPI int conf_loader(void)
343 {
344         FILE *fp;
345         int c;
346         enum state {
347                 START,
348                 SPACE,
349                 TOKEN,
350                 VALUE,
351                 ERROR,
352                 COMMENT,
353                 END,
354         } state;
355         int ch_idx;
356         int token_idx;
357         int buffer_idx;
358         int quote;
359         int linelen;
360         char buffer[256];
361         static const struct token_parser {
362                 const char *name;
363                 void (*handler)(char *buffer);
364         } token_handler[] = {
365                 {
366                         .name = "base_width",
367                         .handler = base_width_handler,
368                 },
369                 {
370                         .name = "base_height",
371                         .handler = base_height_handler,
372                 },
373                 {
374                         .name = "minimum_period",
375                         .handler = minimum_period_handler,
376                 },
377                 {
378                         .name = "script",
379                         .handler = script_handler,
380                 },
381                 {
382                         .name = "default_abi",
383                         .handler = default_abi_handler,
384                 },
385                 {
386                         .name = "default_group",
387                         .handler = default_group_handler,
388                 },
389                 {
390                         .name = "default_period",
391                         .handler = default_period_handler,
392                 },
393                 {
394                         .name = "default_packet_time",
395                         .handler = default_packet_time_handler,
396                 },
397                 {
398                         .name = "default_content",
399                         .handler = default_content_handler,
400                 },
401                 {
402                         .name = "default_title",
403                         .handler = default_title_handler,
404                 },
405                 {
406                         .name = "minimum_space",
407                         .handler = minimum_space_handler,
408                 },
409                 {
410                         .name = "replace_tag",
411                         .handler = replace_tag_handler,
412                 },
413                 {
414                         .name = "slave_ttl",
415                         .handler = slave_ttl_handler,
416                 },
417                 {
418                         .name = "slave_activate_time",
419                         .handler = slave_activate_time_handler,
420                 },
421                 {
422                         .name = "max_log_line",
423                         .handler = max_log_line_handler,
424                 },
425                 {
426                         .name = "max_log_file",
427                         .handler = max_log_file_handler,
428                 },
429                 {
430                         .name = "sqilte_flush_max",
431                         .handler = sqlite_flush_max_handler,
432                 },
433                 {
434                         .name = "db_path",
435                         .handler = db_path_handler,
436                 },
437                 {
438                         .name = "log_path",
439                         .handler = log_path_handler,
440                 },
441                 {
442                         .name = "reader_path",
443                         .handler = reader_path_handler,
444                 },
445                 {
446                         .name = "always_path",
447                         .handler = always_path_handler,
448                 },
449                 {
450                         .name = "share_path",
451                         .handler = share_path_handler,
452                 },
453                 {
454                         .name = "script_port_path",
455                         .handler = script_port_path_handler,
456                 },
457                 {
458                         .name = "ping_interval",
459                         .handler = ping_time_handler,
460                 },
461                 {
462                         .name = "slave_max_load",
463                         .handler = slave_max_loader,
464                 },
465                 {
466                         .name = "use_sw_backend",
467                         .handler = use_sw_backend_handler,
468                 },
469                 {
470                         .name = "use_xmonitor",
471                         .handler = use_xmonitor,
472                 },
473                 {
474                         .name = "provider_method",
475                         .handler = provider_method_handler,
476                 },
477                 {
478                         .name = "debug_mode",
479                         .handler = debug_mode_handler,
480                 },
481                 {
482                         .name = "overwrite_content",
483                         .handler = overwrite_content_handler,
484                 },
485                 {
486                         .name = "com_core_thread",
487                         .handler = com_core_thread_handler,
488                 },
489                 {
490                         .name = "input",
491                         .handler = input_path_handler,
492                 },
493                 {
494                         .name = "pd_request_timeout",
495                         .handler = pd_request_timeout_handler,
496                 },
497                 {
498                         .name = NULL,
499                         .handler = NULL,
500                 },
501         };
502
503         conf_update_size();
504
505         fp = fopen("/usr/share/data-provider-master/conf.ini", "rt");
506         if (!fp) {
507                 ErrPrint("Error: %s\n", strerror(errno));
508                 return LB_STATUS_ERROR_IO;
509         }
510
511         state = START;
512         ch_idx = 0;
513         token_idx = -1;
514         buffer_idx = 0;
515         quote = 0;
516         linelen = 0;
517         do {
518                 c = getc(fp);
519                 if ((c == EOF) && (state == VALUE)) {
520                         DbgPrint("[%s:%d] VALUE state EOF\n", __func__, __LINE__);
521                         state = END;
522                 }
523
524                 switch (state) {
525                 case COMMENT:
526                         if (c == CR || c == LF || c == EOF) {
527                                 buffer[buffer_idx] = '\0';
528
529                                 state = START;
530                                 token_idx = -1;
531                                 ch_idx = 0;
532                                 buffer_idx = 0;
533                                 linelen = -1; /* Will be ZERO by follwing increment code */
534                                 quote = 0;
535                         } else {
536                                 buffer[buffer_idx++] = c;
537                                 if (buffer_idx == (sizeof(buffer) - 1)) {
538                                         buffer[buffer_idx] = '\0';
539                                         buffer_idx = 0;
540                                 }
541                         }
542                         break;
543                 case START:
544                         if (linelen == 0 && c == '#') {
545                                 state = COMMENT;
546                         } else if (isspace(c)) {
547                                 /* Ignore empty space */
548                         } else {
549                                 state = TOKEN;
550                                 ungetc(c, fp);
551                         }
552                         break;
553                 case SPACE:
554                         if (c == '=')
555                                 state = VALUE;
556                         else if (!isspace(c))
557                                 state = ERROR;
558                         break;
559                 case VALUE:
560                         if (c == '"') {
561                                 if (quote == 1) {
562                                         buffer[buffer_idx] = '\0';
563                                         state = END;
564                                 } else if (buffer_idx != 0) {
565                                         buffer[buffer_idx++] = c;
566                                         if (buffer_idx >= sizeof(buffer))
567                                                 state = ERROR;
568                                 } else {
569                                         quote = 1;
570                                 }
571                         } else if (isspace(c)) {
572                                 if (buffer_idx == 0) {
573                                         /* Ignore */
574                                 } else if (quote == 1) {
575                                         buffer[buffer_idx++] = c;
576                                         if (buffer_idx >= sizeof(buffer))
577                                                 state = ERROR;
578                                 } else {
579                                         buffer[buffer_idx] = '\0';
580                                         ungetc(c, fp);
581                                         state = END;
582                                 }
583                         } else {
584                                 buffer[buffer_idx++] = c;
585                                 if (buffer_idx >= sizeof(buffer))
586                                         state = ERROR;
587                         }
588                         break;
589                 case TOKEN:
590                         if (c == '=') {
591                                 if (token_idx < 0)
592                                         state = ERROR;
593                                 else
594                                         state = VALUE;
595                         } else if (isspace(c)) {
596                                 if (token_idx < 0)
597                                         break;
598
599                                 if (token_handler[token_idx].name[ch_idx] != '\0')
600                                         state = ERROR;
601                                 else
602                                         state = SPACE;
603                         } else  {
604                                 if (token_idx < 0) {
605                                         /* Now start to find a token! */
606                                         token_idx = 0;
607                                 }
608
609                                 if (token_handler[token_idx].name[ch_idx] == c) {
610                                         ch_idx++;
611                                 } else {
612                                         ungetc(c, fp);
613                                         while (ch_idx-- > 0)
614                                                 ungetc(token_handler[token_idx].name[ch_idx], fp);
615
616                                         token_idx++;
617
618                                         if (token_handler[token_idx].name == NULL)
619                                                 state = ERROR;
620                                         else
621                                                 ch_idx = 0;
622                                 }
623                         }
624                         break;
625                 case ERROR:
626                         if (c == CR || c == LF || c == EOF) {
627                                 state = START;
628                                 token_idx = -1;
629                                 buffer_idx = 0;
630                                 ch_idx = 0;
631                                 linelen = -1;
632                                 quote = 0;
633                         }
634                         break;
635                 case END:
636                         if (c == LF || c == CR || c == EOF) {
637                                 state = START;
638
639                                 if (token_idx >= 0 && token_handler[token_idx].handler) {
640                                         buffer[buffer_idx] = '\0';
641                                         DbgPrint("BUFFER: [%s]\n", buffer);
642                                         token_handler[token_idx].handler(buffer);
643                                 }
644
645                                 token_idx = -1;
646                                 ch_idx = 0;
647                                 buffer_idx = 0;
648                                 linelen = -1;
649                                 quote = 0;
650                                 /* Finish */
651                         } else if (isspace(c)) {
652                                 /* ignore */
653                         } else {
654                                 state = ERROR;
655                         }
656                         break;
657                 default:
658                         /* ?? */
659                         break;
660                 }
661
662                 linelen++;
663          } while (c != EOF);
664
665         if (fclose(fp) != 0)
666                 ErrPrint("fclose: %s\n", strerror(errno));
667         return LB_STATUS_SUCCESS;
668 }
669
670 /* End of a file */