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