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