dd73037a92e480d7daa0df26d26f3c608d69bf5e
[platform/framework/web/wrt.git] / src / wrt-launchpad-daemon / launchpad_src / launchpad.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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
18 /*
19  * simple AUL daemon - launchpad 
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <dlfcn.h>
25 #include <X11/Xlib.h>
26 #include <sys/types.h>
27 #include <signal.h>
28 #include <dirent.h>
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <sys/wait.h>
32 #include <poll.h>
33 #include <sys/prctl.h>
34 #include <malloc.h>
35
36 #include "app_sock.h"
37 #include <aul.h>
38
39 #include "config.h"
40
41 #include "menu_db_util.h"
42 #include "simple_util.h"
43 #include "access_control.h"
44 #include "preload.h"
45 #include "preexec.h"
46 #include "perf.h"
47 #include "sigchild.h"
48 #include "aul_util.h"
49
50 #include "util_x.h"
51
52 #include "gl.h"
53
54 #include <app-checker.h>
55 #include <sqlite3.h>
56
57 #define _static_ static inline
58 #define POLLFD_MAX 1
59 #define SQLITE_FLUSH_MAX        (1048576)       /* (1024*1024) */
60 #define AUL_POLL_CNT            15
61 #define AUL_PR_NAME                     16
62 #define PATH_APP_ROOT "/opt/usr/apps"
63 #define PATH_DATA "/data"
64 #define SDK_CODE_COVERAGE "CODE_COVERAGE"
65 #define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
66 #define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so"
67
68
69 static char *launchpad_cmdline;
70 static int initialized = 0;
71
72
73 _static_ void __set_oom();
74 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb);
75 _static_ int __prepare_exec(const char *pkg_name,
76                             const char *app_path, app_info_from_db * menu_info,
77                             bundle * kb);
78 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb);
79 _static_ char **__create_argc_argv(bundle * kb, int *margc);
80 _static_ int __normal_fork_exec(int argc, char **argv);
81 _static_ void __real_launch(const char *app_path, bundle * kb);
82 static inline int __parser(const char *arg, char *out, int out_size);
83 _static_ void __modify_bundle(bundle * kb, int caller_pid,
84                             app_info_from_db * menu_info, int cmd);
85 _static_ int __child_raise_win_by_x(int pid, void *priv);
86 _static_ int __raise_win_by_x(int pid);
87 _static_ int __send_to_sigkill(int pid);
88 _static_ int __term_app(int pid);
89 _static_ int __resume_app(int pid);
90 _static_ void __real_send(int clifd, int ret);
91 _static_ void __send_result_to_caller(int clifd, int ret);
92 _static_ void __launchpad_main_loop(int main_fd);
93 _static_ int __launchpad_pre_init(int argc, char **argv);
94 _static_ int __launchpad_post_init();
95
96 extern ail_error_e ail_db_close(void);
97
98
99
100 _static_ void __set_oom()
101 {
102         char buf[MAX_LOCAL_BUFSZ];
103         FILE *fp;
104
105         /* we should reset oomadj value as default because child 
106         inherits from parent oom_adj*/
107         snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
108         fp = fopen(buf, "w");
109         if (fp == NULL)
110                 return;
111         fprintf(fp, "%d", -16);
112         fclose(fp);
113 }
114
115 _static_ void __set_sdk_env(app_info_from_db* menu_info, char* str) {
116         char buf[MAX_LOCAL_BUFSZ];
117         int ret;
118
119         _D("key : %s / value : %s", AUL_K_SDK, str);
120         /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
121         /* GCOV_PREFIX contains the prefix to add to the absolute paths in the object file. */
122         /*              Prefix can be absolute, or relative. The default is no prefix.  */
123         /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
124         /*              to stripoff the hardwired absolute paths. Default value is 0. */
125         if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
126                 snprintf(buf, MAX_LOCAL_BUFSZ, PATH_APP_ROOT"/%s"PATH_DATA, _get_pkgname(menu_info));
127                 ret = setenv("GCOV_PREFIX", buf, 1);
128                 _D("GCOV_PREFIX : %d", ret);
129                 ret = setenv("GCOV_PREFIX_STRIP", "4096", 1);
130                 _D("GCOV_PREFIX_STRIP : %d", ret);
131         } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
132                 ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
133                 _D("LD_PRELOAD : %d", ret);
134         }
135 }
136
137
138 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
139 {
140         const char *str;
141         const char **str_array;
142         int len;
143         int i;
144
145         setenv("PKG_NAME", _get_pkgname(menu_info), 1);
146
147         USE_ENGINE("gl")
148
149         str = bundle_get_val(kb, AUL_K_STARTTIME);
150         if (str != NULL)
151                 setenv("APP_START_TIME", str, 1);
152
153         if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
154                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
155                 if(str_array != NULL) {
156                         for (i = 0; i < len; i++) {
157                                 _D("index : [%d]", i);
158                                 __set_sdk_env(menu_info, (char *)str_array[i]);
159                         }
160                 }
161         } else {
162                 str = bundle_get_val(kb, AUL_K_SDK);
163                 if(str != NULL) {
164                         __set_sdk_env(menu_info, (char *)str);
165                 }
166         }
167         if (menu_info->hwacc != NULL)
168                 setenv("HWACC", menu_info->hwacc, 1);
169 }
170
171 _static_ int __prepare_exec(const char *pkg_name,
172                             const char *app_path, app_info_from_db * menu_info,
173                             bundle * kb)
174 {
175         char *file_name;
176         char process_name[AUL_PR_NAME];
177
178         /* Set new session ID & new process group ID*/
179         /* In linux, child can set new session ID without check permission */
180         /* TODO : should be add to check permission in the kernel*/
181         setsid();
182
183         __preexec_run(menu_info->pkg_type, pkg_name, app_path);
184
185         /* SET OOM*/
186         __set_oom();
187
188         /* SET PRIVILEGES*/
189         if (__set_access(pkg_name, menu_info->pkg_type, app_path) < 0) {
190                  _D("fail to set privileges - check your package's credential\n");
191                 return -1;
192         }
193         /* SET DUMPABLE - for coredump*/
194         prctl(PR_SET_DUMPABLE, 1);
195
196         /* SET PROCESS NAME*/
197         if (app_path == NULL) {
198                 _D("app_path should not be NULL - check menu db");
199                 return -1;
200         }
201         file_name = strrchr(app_path, '/') + 1;
202         if (file_name == NULL) {
203                 _D("can't locate file name to execute");
204                 return -1;
205         }
206         memset(process_name, '\0', AUL_PR_NAME);
207         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
208         prctl(PR_SET_NAME, process_name);
209
210         /* SET ENVIROMENT*/
211         __set_env(menu_info, kb);
212
213         return 0;
214 }
215
216 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb)
217 {
218         int datalen;
219         int ret;
220         bundle_raw *kb_data;
221
222         bundle_encode(kb, &kb_data, &datalen);
223         if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
224                 _E("error request fake launch - error code = %d", ret);
225         free(kb_data);
226         return ret;
227 }
228
229 _static_ char **__create_argc_argv(bundle * kb, int *margc)
230 {
231         char **argv;
232         int argc;
233
234         argc = bundle_export_to_argv(kb, &argv);
235
236         *margc = argc;
237         return argv;
238 }
239
240 _static_ int __normal_fork_exec(int argc, char **argv)
241 {
242         _D("start real fork and exec\n");
243
244         // warning: unused parameter
245         argc = argc;
246
247         if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
248                 if (errno == EACCES)
249                         _E("such a file is no executable - %s", argv[0]);
250                 else
251                         _E("unknown executable error - %s", argv[0]);
252                 return -1;
253         }
254         /* never reach*/
255         return 0;
256 }
257
258 _static_ void __real_launch(const char *app_path, bundle * kb)
259 {
260         int app_argc;
261         char **app_argv;
262         int i;
263
264         app_argv = __create_argc_argv(kb, &app_argc);
265
266 #ifndef NATIVE_LAUNCHPAD
267     if (__change_cmdline(app_path) < 0) {
268         _E("change cmdline fail");
269         return;
270     }
271
272     app_argv[0] = g_argv[0];
273 #else
274         app_argv[0] = strdup(app_path);
275 #endif
276
277         for (i = 0; i < app_argc; i++)
278                 _D("input argument %d : %s##", i, app_argv[i]);
279
280         PERF("setup argument done");
281         _E("lock up test log(no error) : setup argument done");
282
283         /* Temporary log: launch time checking */
284         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
285
286         __preload_exec(app_argc, app_argv);
287
288         __normal_fork_exec(app_argc, app_argv);
289 }
290
291 /*
292  * Parsing original app path to retrieve default bundle
293  *
294  * -1 : Invalid sequence
295  * -2 : Buffer overflow
296  *
297  */
298 static inline int __parser(const char *arg, char *out, int out_size)
299 {
300         register int i;
301         int state = 1;
302         char *start_out = out;
303
304         if (arg == NULL || out == NULL) {
305                 /* Handles null buffer*/
306                 return 0;
307         }
308
309         for (i = 0; out_size > 1; i++) {
310                 switch (state) {
311                 case 1:
312                         switch (arg[i]) {
313                         case ' ':
314                         case '\t':
315                                 state = 5;
316                                 break;
317                         case '\0':
318                                 state = 7;
319                                 break;
320                         case '\"':
321                                 state = 2;
322                                 break;
323                         case '\\':
324                                 state = 4;
325                                 break;
326                         default:
327                                 *out = arg[i];
328                                 out++;
329                                 out_size--;
330                                 break;
331                         }
332                         break;
333                 case 2: /* escape start*/
334                         switch (arg[i]) {
335                         case '\0':
336                                 state = 6;
337                                 break;
338                         case '\"':
339                                 state = 1;
340                                 break;
341                         default:
342                                 *out = arg[i];
343                                 out++;
344                                 out_size--;
345                                 break;
346                         }
347                         break;
348                 case 4: /* character escape*/
349                         if (arg[i] == '\0') {
350                                 state = 6;
351                         } else {
352                                 *out = arg[i];
353                                 out++;
354                                 out_size--;
355                                 state = 1;
356                         }
357                         break;
358                 case 5: /* token*/
359                         if (out != start_out) {
360                                 *out = '\0';
361                                 out_size--;
362                                 return i;
363                         }
364                         i--;
365                         state = 1;
366                         break;
367                 case 6:
368                         return -1;      /* error*/
369                 case 7: /* terminate*/
370                         *out = '\0';
371                         out_size--;
372                         return 0;
373                 default:
374                         state = 6;
375                         break;  /* error*/
376                 }
377         }
378
379         if (out_size == 1) {
380                 *out = '\0';
381         }
382         /* Buffer overflow*/
383         return -2;
384 }
385
386 _static_ void __modify_bundle(bundle * kb, int caller_pid,
387                             app_info_from_db * menu_info, int cmd)
388 {
389         // warning: unused parameter
390         caller_pid = caller_pid;
391
392         bundle_del(kb, AUL_K_PKG_NAME);
393         bundle_del(kb, AUL_K_EXEC);
394         bundle_del(kb, AUL_K_PACKAGETYPE);
395         bundle_del(kb, AUL_K_HWACC);
396
397         /* Parse app_path to retrieve default bundle*/
398         if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd == APP_RESUME) {
399                 char *ptr;
400                 char exe[MAX_PATH_LEN];
401                 int flag;
402
403                 ptr = _get_original_app_path(menu_info);
404
405                 flag = __parser(ptr, exe, sizeof(exe));
406                 if (flag > 0) {
407                         char key[256];
408                         char value[256];
409
410                         ptr += flag;
411                         _D("parsing app_path: EXEC - %s\n", exe);
412
413                         do {
414                                 flag = __parser(ptr, key, sizeof(key));
415                                 if (flag <= 0)
416                                         break;
417                                 ptr += flag;
418
419                                 flag = __parser(ptr, value, sizeof(value));
420                                 if (flag < 0)
421                                         break;
422                                 ptr += flag;
423
424                                 /*bundle_del(kb, key);*/
425                                 bundle_add(kb, key, value);
426                         } while (flag > 0);
427                 } else if (flag == 0) {
428                         _D("parsing app_path: No arguments\n");
429                 } else {
430                         _D("parsing app_path: Invalid argument\n");
431                 }
432         }
433 }
434
435 _static_ int __child_raise_win_by_x(int pid, void *priv)
436 {
437         // warning: unused parameter
438         priv = priv;
439
440         return x_util_raise_win(pid);
441 }
442
443 _static_ int __raise_win_by_x(int pid)
444 {
445         int pgid;
446         if (x_util_raise_win(pid) == 0)
447                 return 0;
448
449         /* support app launched by shell script*/
450         pgid = getpgid(pid);
451         _D("X raise failed. try to find first child & raise it - c:%d p:%d\n",
452            pgid, pid);
453
454         if (pgid <= 1)
455                 return -1;
456         if (__proc_iter_pgid(pgid, __child_raise_win_by_x, NULL) < 0)
457                 return -1;
458
459         return 0;
460 }
461
462 _static_ int __send_to_sigkill(int pid)
463 {
464         int pgid;
465
466         pgid = getpgid(pid);
467         if (pgid <= 1)
468                 return -1;
469
470         if (killpg(pgid, SIGKILL) < 0)
471                 return -1;
472
473         return 0;
474 }
475
476 _static_ int __term_app(int pid)
477 {
478         int dummy;
479         if (__app_send_raw
480             (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
481                 _D("terminate packet send error - use SIGKILL");
482                 if (__send_to_sigkill(pid) < 0) {
483                         _E("fail to killing - %d\n", pid);
484                         return -1;
485                 }
486         }
487         _D("term done\n");
488         return 0;
489 }
490
491 _static_ int __resume_app(int pid)
492 {
493         int dummy;
494         int ret;
495         if ((ret =
496              __app_send_raw(pid, APP_RESUME_BY_PID, (unsigned char *)&dummy,
497                             sizeof(int))) < 0) {
498                 if (ret == -EAGAIN)
499                         _E("resume packet timeout error");
500                 else {
501                         _D("resume packet send error - use raise win");
502                         if (__raise_win_by_x(pid) < 0) {
503                                 _E("raise failed - %d resume fail\n", pid);
504                                 _E("we will term the app - %d\n", pid);
505                                 __send_to_sigkill(pid);
506                                 ret = -1;
507                         } else
508                                 ret = 0;
509                 }
510         }
511         _D("resume done\n");
512         return ret;
513 }
514
515 static int __get_caller_pid(bundle *kb)
516 {
517         const char *pid_str;
518         int pid;
519
520         pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
521         if(pid_str)
522                 goto end;
523
524         pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
525         if (pid_str == NULL)
526                 return -1;
527
528 end:
529         pid = atoi(pid_str);
530         if (pid <= 1)
531                 return -1;
532
533         return pid;
534 }
535
536 _static_ int __foward_cmd(int cmd, bundle *kb, int cr_pid)
537 {
538         int pid;
539         char tmp_pid[MAX_PID_STR_BUFSZ];
540         int datalen;
541         bundle_raw *kb_data;
542         int res;
543
544         if ((pid = __get_caller_pid(kb)) < 0)
545                         return AUL_R_ERROR;
546
547         snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
548
549         bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
550
551         bundle_encode(kb, &kb_data, &datalen);
552         if ((res = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
553                 res = AUL_R_ERROR;
554
555         free(kb_data);
556
557         return res;
558 }
559
560 _static_ void __real_send(int clifd, int ret)
561 {
562         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
563                 if (errno == EPIPE) {
564                         _E("send failed due to EPIPE.\n");
565                 }
566                 _E("send fail to client");
567         }
568
569         close(clifd);
570 }
571
572 _static_ void __send_result_to_caller(int clifd, int ret)
573 {
574         char *cmdline;
575         int wait_count;
576         int cmdline_changed = 0;
577         int cmdline_exist = 0;
578
579         if (clifd == -1)
580                 return;
581
582         if (ret <= 1) {
583                 __real_send(clifd, ret);
584                 return;
585         }
586         /* check normally was launched?*/
587         wait_count = 1;
588         do {
589                 cmdline = __proc_get_cmdline_bypid(ret);
590                 if (cmdline == NULL) {
591                         _E("error founded when being launched with %d", ret);
592
593                 } else if (strcmp(cmdline, launchpad_cmdline)) {
594                         free(cmdline);
595                         cmdline_changed = 1;
596                         break;
597                 } else {
598                         cmdline_exist = 1;
599                         free(cmdline);
600                 }
601
602                 _D("-- now wait to change cmdline --");
603                 usleep(50 * 1000);      /* 50ms sleep*/
604                 wait_count++;
605         } while (wait_count <= 20);     /* max 50*20ms will be sleep*/
606
607         if ((!cmdline_exist) && (!cmdline_changed)) {
608                 __real_send(clifd, -1); /* abnormally launched*/
609                 return;
610         }
611
612         if (!cmdline_changed)
613                 _E("process launched, but cmdline not changed");
614
615         __real_send(clifd, ret);
616         return;
617 }
618
619 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
620                                                         const char *pkgname, bundle *kb)
621 {
622         app_info_from_db *menu_info;
623
624         menu_info = calloc(1, sizeof(app_info_from_db));
625         if (menu_info == NULL) {
626                 return NULL;
627         }
628
629         menu_info->pkg_name = strdup(pkgname);
630         menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
631         if (menu_info->app_path != NULL)
632                 menu_info->original_app_path = strdup(menu_info->app_path);
633         menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
634         menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
635
636         if (!_get_app_path(menu_info)) {
637                 _free_app_info_from_db(menu_info);
638                 return NULL;
639         }
640
641         return menu_info;
642 }
643
644 _static_ void __launchpad_main_loop(int main_fd)
645 {
646         bundle *kb = NULL;
647         app_pkt_t *pkt = NULL;
648         app_info_from_db *menu_info = NULL;
649
650         const char *pkg_name = NULL;
651         const char *app_path = NULL;
652         int pid = -1;
653         int clifd = -1;
654         struct ucred cr;
655         int is_real_launch = 0;
656
657         char sock_path[UNIX_PATH_MAX] = {0,};
658
659         pkt = __app_recv_raw(main_fd, &clifd, &cr);
660         if (!pkt) {
661                 _D("packet is NULL");
662                 goto end;
663         }
664
665         kb = bundle_decode(pkt->data, pkt->len);
666         if (!kb) {
667                 _D("bundle decode error");
668                 goto end;
669         }
670
671         INIT_PERF(kb);
672         PERF("packet processing start");
673
674         pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
675         _D("pkg name : %s\n", pkg_name);
676
677         menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
678         if (menu_info == NULL) {
679                 _D("such pkg no found");
680                 goto end;
681         }
682
683         app_path = _get_app_path(menu_info);
684         if(app_path == NULL) {
685                 _E("app_path is NULL");
686                 goto end;
687         }
688         if (app_path[0] != '/') {
689                 _D("app_path is not absolute path");
690                 goto end;
691         }
692
693         __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
694         pkg_name = _get_pkgname(menu_info);
695
696         PERF("get package information & modify bundle done");
697
698         {
699                 pid = fork();
700                 if (pid == 0) {
701                         PERF("fork done");
702                         _E("lock up test log(no error) : fork done");
703
704                         close(clifd);
705                         close(main_fd);
706                         __signal_unset_sigchld();
707                         __signal_fini();
708
709                         snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid());
710                         unlink(sock_path);
711
712                         PERF("prepare exec - first done");
713                         _E("lock up test log(no error) : prepare exec - first done");
714
715                         if (__prepare_exec(pkg_name, app_path,
716                                            menu_info, kb) < 0) {
717                                 _E("preparing work fail to launch - "
718                                    "can not launch %s\n", pkg_name);
719                                 exit(-1);
720                         }
721
722                         PERF("prepare exec - second done");
723                         _E("lock up test log(no error) : prepare exec - second done");
724
725                         __real_launch(app_path, kb);
726
727                         exit(-1);
728                 }
729                 _D("==> real launch pid : %d %s\n", pid, app_path);
730                 is_real_launch = 1;
731         }
732
733  end:
734         __send_result_to_caller(clifd, pid);
735
736         if (pid > 0) {
737                 if (is_real_launch) {
738                         /*TODO: retry*/
739                         __signal_block_sigchld();
740                         __send_app_launch_signal(pid);
741                         __signal_unblock_sigchld();
742                 }
743         }
744
745         if (menu_info != NULL)
746                 _free_app_info_from_db(menu_info);
747
748         if (kb != NULL)
749                 bundle_free(kb);
750         if (pkt != NULL)
751                 free(pkt);
752
753         /* Active Flusing for Daemon */
754         if (initialized > AUL_POLL_CNT) {
755                 sqlite3_release_memory(SQLITE_FLUSH_MAX);
756                 malloc_trim(0);
757                 initialized = 1;
758         }
759
760 }
761
762 _static_ int __launchpad_pre_init(int argc, char **argv)
763 {
764         int fd;
765
766         /* signal init*/
767         __signal_init();
768
769         /* get my(launchpad) command line*/
770         launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
771         if (launchpad_cmdline == NULL) {
772                 _E("launchpad cmdline fail to get");
773                 return -1;
774         }
775         _D("launchpad cmdline = %s", launchpad_cmdline);
776
777         /* create launchpad sock        */
778         fd = __create_server_sock(WRT_LAUNCHPAD_PID);
779         if (fd < 0) {
780                 _E("server sock error");
781                 return -1;
782         }
783
784         __preload_init(argc, argv);
785
786     __preload_init_for_wrt();
787
788         __preexec_init(argc, argv);
789
790         return fd;
791 }
792
793 _static_ int __launchpad_post_init()
794 {
795         /* Setting this as a global variable to keep track 
796         of launchpad poll cnt */
797         /* static int initialized = 0;*/
798
799         if (initialized) {
800                 initialized++;
801                 return 0;
802         }
803
804         if (__signal_set_sigchld() < 0)
805                 return -1;
806
807         initialized++;
808
809         return 0;
810 }
811
812 int main(int argc, char **argv)
813 {
814         int main_fd;
815         struct pollfd pfds[POLLFD_MAX];
816         int i;
817
818         /* init without concerning X & EFL*/
819         main_fd = __launchpad_pre_init(argc, argv);
820         if (main_fd < 0) {
821                 _E("launchpad pre init failed");
822                 exit(-1);
823         }
824
825         pfds[0].fd = main_fd;
826         pfds[0].events = POLLIN;
827         pfds[0].revents = 0;
828
829         while (1) {
830                 if (poll(pfds, POLLFD_MAX, -1) < 0)
831                         continue;
832
833                 /* init with concerning X & EFL (because of booting 
834                 sequence problem)*/
835                 if (__launchpad_post_init() < 0) {
836                         _E("launcpad post init failed");
837                         exit(-1);
838                 }
839
840                 for (i = 0; i < POLLFD_MAX; i++) {
841                         if ((pfds[i].revents & POLLIN) != 0) {
842                                 __launchpad_main_loop(pfds[i].fd);
843                         }
844                 }
845         }
846 }
847