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