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