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