f2458f985124615a452ebeb4e9dfa6919407c82b
[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  * simple AUL daemon - launchpad 
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <dlfcn.h>
29 #include <X11/Xlib.h>
30 #include <sys/types.h>
31 #include <signal.h>
32 #include <dirent.h>
33 #include <fcntl.h>
34 #include <stdlib.h>
35 #include <sys/wait.h>
36 #include <poll.h>
37 #include <sys/prctl.h>
38 #include <malloc.h>
39
40 #include "app_sock.h"
41 #include "aul.h"
42
43 #include "config.h"
44
45 #include "menu_db_util.h"
46 #include "simple_util.h"
47 #include "access_control.h"
48 #include "preload.h"
49 #include "preexec.h"
50 #include "perf.h"
51 #include "sigchild.h"
52 #include "aul_util.h"
53
54 #include "heap_dbg.h"
55
56 #include "gl.h"
57
58 #include <sqlite3.h>
59 #include <sys/smack.h>
60 #include "fileutils.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 #define SDK_VALGRIND "VALGRIND"
76
77 /* DLP is short for debug-launchpad */
78 #define DLP_K_DEBUG_ARG "__DLP_DEBUG_ARG__"
79 #define DLP_K_UNIT_TEST_ARG "__DLP_UNIT_TEST_ARG__"
80 #define DLP_K_VALGRIND_ARG "__DLP_VALGRIND_ARG__"
81
82 #define PATH_GDBSERVER  "/home/developer/sdk_tools/gdbserver/gdbserver"
83 #define PATH_VALGRIND   "/home/developer/sdk_tools/valgrind/usr/bin/valgrind"
84 #define PATH_DA_SO      "/usr/lib/da_probe_osp.so"
85 #define PATH_NATIVE_APP "/opt/apps/"
86
87 #define OPT_VALGRIND_LOGFILE            "--log-file="
88 #define OPT_VALGRIND_LOGFILE_FIXED      "--log-file=/tmp/valgrind_result.txt"
89 #define PATH_VALGRIND_LOGFILE           "/tmp/valgrind_result.txt"
90 #define OPT_VALGRIND_XMLFILE            "--xml-file="
91 #define OPT_VALGRIND_XMLFILE_FIXED      "--xml-file=/tmp/valgrind_result.xml"
92 #define PATH_VALGRIND_XMLFILE           "/tmp/valgrind_result.xml"
93
94 #define POLL_VALGRIND_LOGFILE           0x00000001
95 #define POLL_VALGRIND_XMLFILE           0x00000002
96
97 static char *launchpad_cmdline;
98 static int initialized = 0;
99
100 static int poll_outputfile = 0;
101
102 void __set_oom();
103 void __set_env(app_info_from_db * menu_info, bundle * kb);
104 int __prepare_exec(const char *pkg_name,
105                             const char *app_path, app_info_from_db * menu_info,
106                             bundle * kb);
107 int __fake_launch_app(int cmd, int pid, bundle * kb);
108 char **__create_argc_argv(bundle * kb, int *margc, const char *app_path);
109 int __normal_fork_exec(int argc, char **argv);
110 void __real_launch(const char *app_path, bundle * kb);
111 static inline int __parser(const char *arg, char *out, int out_size);
112 void __modify_bundle(bundle * kb, int caller_pid,
113                             app_info_from_db * menu_info, int cmd);
114 int __send_to_sigkill(int pid);
115 int __term_app(int pid);
116 void __real_send(int clifd, int ret);
117 void __send_result_to_caller(int clifd, int ret);
118 void __launchpad_main_loop(int main_fd);
119 int __launchpad_pre_init(int argc, char **argv);
120 int __launchpad_post_init();
121
122 extern ail_error_e ail_db_close(void);
123
124
125
126 void __set_oom()
127 {
128         char buf[MAX_LOCAL_BUFSZ];
129         FILE *fp;
130
131         /* we should reset oomadj value as default because child 
132         inherits from parent oom_adj*/
133         snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
134         fp = fopen(buf, "w");
135         if (fp == NULL)
136                 return;
137         fprintf(fp, "%d", -16);
138         fclose(fp);
139 }
140
141 void __set_sdk_env(app_info_from_db* menu_info, char* str) {
142         char buf_pkgname[MAX_LOCAL_BUFSZ];
143         char buf[MAX_LOCAL_BUFSZ];
144         int ret;
145
146         _D("key : %s / value : %s", AUL_K_SDK, str);
147         /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
148         /* GCOV_PREFIX contains the prefix to add to the absolute paths */
149         /*      in the object file. Prefix can be absolute, or relative.*/
150         /*      The default is no prefix.  */
151         /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
152         /*      to stripoff the hardwired absolute paths. Default value is 0. */
153         if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
154                 strncpy(buf_pkgname,_get_pkgname(menu_info),MAX_LOCAL_BUFSZ-1);
155                 buf_pkgname[MAX_LOCAL_BUFSZ-1]='\0';
156                 snprintf(buf, MAX_LOCAL_BUFSZ, PATH_TMP"/%s"PATH_DATA
157                         , strtok(buf_pkgname,"."));
158                 ret = setenv("GCOV_PREFIX", buf, 1);
159                 _D("GCOV_PREFIX : %d", ret);
160                 ret = setenv("GCOV_PREFIX_STRIP", "0", 1);
161                 _D("GCOV_PREFIX_STRIP : %d", ret);
162         } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
163                 ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
164                 _D("LD_PRELOAD : %d", ret);
165         }
166 }
167
168
169 void __set_env(app_info_from_db * menu_info, bundle * kb)
170 {
171         const char *str;
172         const char **str_array;
173         int len;
174         int i;
175
176         setenv("PKG_NAME", _get_pkgname(menu_info), 1);
177
178         USE_ENGINE("gl")
179
180         str = bundle_get_val(kb, AUL_K_STARTTIME);
181         if (str != NULL)
182                 setenv("APP_START_TIME", str, 1);
183
184         if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
185                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
186                 if(str_array != NULL) {
187                         for (i = 0; i < len; i++) {
188                                 _D("index : [%d]", i);
189                                 __set_sdk_env(menu_info, (char *)str_array[i]);
190                         }
191                 }
192         } else {
193                 str = bundle_get_val(kb, AUL_K_SDK);
194                 if(str != NULL) {
195                         __set_sdk_env(menu_info, (char *)str);
196                 }
197         }
198         if (menu_info->hwacc != NULL)
199                 setenv("HWACC", menu_info->hwacc, 1);
200 }
201
202 int __prepare_exec(const char *pkg_name,
203                             const char *app_path, app_info_from_db * menu_info,
204                             bundle * kb)
205 {
206         char *file_name;
207         char process_name[AUL_PR_NAME];
208         int ret;
209
210         /* Set new session ID & new process group ID*/
211         /* In linux, child can set new session ID without check permission */
212         /* TODO : should be add to check permission in the kernel*/
213         setsid();
214
215         __preexec_run(menu_info->pkg_type, pkg_name, app_path);
216
217         /* SET OOM*/
218         __set_oom();
219
220         /* SET PRIVILEGES*/
221         if(bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) {
222                 _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name
223                         , menu_info->pkg_type, app_path);
224                 if ((ret = __set_access(pkg_name, menu_info->pkg_type
225                         , app_path)) < 0) 
226                 {
227                          _D("fail to set privileges - check your package's credential : %d\n"
228                                 , ret);
229                         return -1;
230                 }
231         }
232         /* SET DUMPABLE - for coredump*/
233         prctl(PR_SET_DUMPABLE, 1);
234
235         /* SET PROCESS NAME*/
236         if (app_path == NULL) {
237                 _D("app_path should not be NULL - check menu db");
238                 return -1;
239         }
240         file_name = strrchr(app_path, '/') + 1;
241         if (file_name == NULL) {
242                 _D("can't locate file name to execute");
243                 return -1;
244         }
245         memset(process_name, '\0', AUL_PR_NAME);
246         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
247         prctl(PR_SET_NAME, process_name);
248
249         /* SET ENVIROMENT*/
250         __set_env(menu_info, kb);
251
252         return 0;
253 }
254
255 int __fake_launch_app(int cmd, int pid, bundle * kb)
256 {
257         int datalen;
258         int ret;
259         bundle_raw *kb_data;
260
261         bundle_encode(kb, &kb_data, &datalen);
262         if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
263                 _E("error request fake launch - error code = %d", ret);
264         free(kb_data);
265         return ret;
266 }
267
268 char** __add_arg(bundle * kb, char **argv, int *margc, const char *key)
269 {
270         const char *str = NULL;
271         const char **str_array = NULL;
272         int len = 0;
273         int i;
274         char ** new_argv = NULL;
275
276         if(bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
277                 str_array = bundle_get_str_array(kb, key, &len);
278         } else {
279                 str = bundle_get_val(kb, key);
280                 if(str) {
281                         str_array = &str;
282                         len = 1;
283                 }
284         }
285         if(str_array != NULL) {
286                 if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
287                         || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
288                 {
289                         new_argv = (char **) realloc(argv
290                                 , sizeof(char *) * (*margc+len+2));
291                         if(!new_argv) {
292                                 _E("realloc fail (key = %s)", key);
293                                 exit(-1);
294                         }
295                         for(i=*margc+len+1; i-(len+1)>=0; i--) {
296                                 new_argv[i] = new_argv[i-(len+1)];
297                         }
298                         // need to add new_argv[0]
299                         for(i=0; i<len; i++) {
300                                 new_argv[1+i] = strdup(str_array[i]);
301                         }
302                         len++;  /* gdbserver or valgrind */
303                         _D("uid : %d", getuid());
304                         _D("euid : %d", geteuid());
305                         _D("gid : %d", getgid());
306                         _D("egid : %d", getegid());
307                 } else {
308                         new_argv = (char **) realloc(argv
309                                 , sizeof(char *) * (*margc+len+1));
310                         if(!new_argv) {
311                                 _E("realloc fail (key = %s)", key);
312                                 exit(-1);
313                         }
314                         for(i=0; i<len; i++) {
315                                 new_argv[*margc+i] = strdup(str_array[i]);
316                         }
317                 }
318                 new_argv[*margc+len] = NULL;
319                 *margc += len;
320         } else {
321                 if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
322                         || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
323                 {
324                         new_argv = (char **) realloc(argv
325                                 , sizeof(char *) * (*margc+2));
326                         if(!new_argv) {
327                                 _E("realloc fail (key = %s)", key);
328                                 exit(-1);
329                         }
330                         for(i=*margc+1; i-1>=0; i--) {
331                                 new_argv[i] = new_argv[i-1];
332                         }
333                         // need to add new_argv[0]
334                         *margc++;
335                 }
336         }
337
338         if(new_argv==NULL) return argv;
339         return new_argv;
340 }
341
342 char **__create_argc_argv(bundle * kb, int *margc, const char *app_path)
343 {
344         char **argv = NULL;
345         char **new_argv = NULL;
346         int argc;
347
348         const char *str = NULL;
349         const char **str_array = NULL;
350         int len = 0;
351         int i;
352
353         argc = bundle_export_to_argv(kb, &argv);
354         if (argv) {
355                 for(i=1; i<argc; i++) {
356                         argv[i] = strdup(argv[i]);
357                 }
358                 argv[0] = strdup(app_path);
359         } else {
360                 _E("bundle_export_to_argv error");
361                 exit(-1);
362         }
363
364         if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
365                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
366         } else {
367                 str = bundle_get_val(kb, AUL_K_SDK);
368                 if(str) {
369                         str_array = &str;
370                         len = 1;
371                 }
372         }
373         if(str_array == NULL) {
374                 *margc = argc;
375                 return argv;
376         }
377
378         for (i = 0; i < len; i++) {
379                 if(str_array[i] == NULL) break;
380                 _D("index : [%d]", i);
381                 /* gdbserver */
382                 if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
383                 {
384                         char buf[MAX_LOCAL_BUFSZ];
385                         if (argv[0]) free(argv[0]);
386                         sprintf(buf,"%s.exe",app_path);
387                         argv[0] = strdup(buf);
388                         new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
389                         new_argv[0] = strdup(PATH_GDBSERVER);
390                 }
391                 /* valgrind */
392                 else if (strncmp(str_array[i], SDK_VALGRIND
393                         , strlen(str_array[i])) == 0)
394                 {
395                         new_argv = __add_arg(kb, argv, &argc
396                                 , DLP_K_VALGRIND_ARG);
397                         new_argv[0] = strdup(PATH_VALGRIND);
398                 }
399                 /* unit test */
400                 else if (strncmp(str_array[i], SDK_UNIT_TEST
401                         , strlen(str_array[i])) == 0)
402                 {
403                         new_argv = __add_arg(kb, argv, &argc
404                                 , DLP_K_UNIT_TEST_ARG);
405                 }
406         }
407
408         *margc = argc;
409         if(new_argv==NULL) return argv;
410         return new_argv;
411 }
412
413 int __normal_fork_exec(int argc, char **argv)
414 {
415         _D("start real fork and exec\n");
416
417         if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
418                 if (errno == EACCES) {
419                         _E("such a file is no executable - %s", argv[0]);
420                 } else {
421                         _E("unknown executable error - %s", argv[0]);
422                 }
423                 return -1;
424         }
425         /* never reach */
426         return 0;
427 }
428
429 void __real_launch(const char *app_path, bundle * kb)
430 {
431         int app_argc;
432         char **app_argv;
433         int i;
434
435         app_argv = __create_argc_argv(kb, &app_argc, app_path);
436
437         for (i = 0; i < app_argc; i++)
438                 _D("input argument %d : %s##", i, app_argv[i]);
439
440         PERF("setup argument done");
441         _D("lock up test log(no error) : setup argument done");
442
443         /* Temporary log: launch time checking */
444         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
445
446         __normal_fork_exec(app_argc, app_argv);
447
448         for(i=0; i<app_argc; i++) {
449                 if(app_argv[i]) free(app_argv[i]);
450         }
451         free(app_argv);
452 }
453
454
455 /*
456  * Parsing original app path to retrieve default bundle
457  *
458  * -1 : Invalid sequence
459  * -2 : Buffer overflow
460  *
461  */
462 static inline int __parser(const char *arg, char *out, int out_size)
463 {
464         register int i;
465         int state = 1;
466         char *start_out = out;
467
468         if (arg == NULL || out == NULL) {
469                 /* Handles null buffer*/
470                 return 0;
471         }
472
473         for (i = 0; out_size > 1; i++) {
474                 switch (state) {
475                 case 1:
476                         switch (arg[i]) {
477                         case ' ':
478                         case '\t':
479                                 state = 5;
480                                 break;
481                         case '\0':
482                                 state = 7;
483                                 break;
484                         case '\"':
485                                 state = 2;
486                                 break;
487                         case '\\':
488                                 state = 4;
489                                 break;
490                         default:
491                                 *out = arg[i];
492                                 out++;
493                                 out_size--;
494                                 break;
495                         }
496                         break;
497                 case 2: /* escape start*/
498                         switch (arg[i]) {
499                         case '\0':
500                                 state = 6;
501                                 break;
502                         case '\"':
503                                 state = 1;
504                                 break;
505                         default:
506                                 *out = arg[i];
507                                 out++;
508                                 out_size--;
509                                 break;
510                         }
511                         break;
512                 case 4: /* character escape*/
513                         if (arg[i] == '\0') {
514                                 state = 6;
515                         } else {
516                                 *out = arg[i];
517                                 out++;
518                                 out_size--;
519                                 state = 1;
520                         }
521                         break;
522                 case 5: /* token*/
523                         if (out != start_out) {
524                                 *out = '\0';
525                                 out_size--;
526                                 return i;
527                         }
528                         i--;
529                         state = 1;
530                         break;
531                 case 6:
532                         return -1;      /* error*/
533                 case 7: /* terminate*/
534                         *out = '\0';
535                         out_size--;
536                         return 0;
537                 default:
538                         state = 6;
539                         break;  /* error*/
540                 }
541         }
542
543         if (out_size == 1) {
544                 *out = '\0';
545         }
546         /* Buffer overflow*/
547         return -2;
548 }
549
550 void __modify_bundle(bundle * kb, int caller_pid,
551                             app_info_from_db * menu_info, int cmd)
552 {
553         bundle_del(kb, AUL_K_PKG_NAME);
554         bundle_del(kb, AUL_K_EXEC);
555         bundle_del(kb, AUL_K_PACKAGETYPE);
556         bundle_del(kb, AUL_K_HWACC);
557
558         /* Parse app_path to retrieve default bundle*/
559         if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN
560                 || cmd == APP_RESUME)
561         {
562                 char *ptr;
563                 char exe[MAX_PATH_LEN];
564                 int flag;
565
566                 ptr = _get_original_app_path(menu_info);
567
568                 flag = __parser(ptr, exe, sizeof(exe));
569                 if (flag > 0) {
570                         char key[256];
571                         char value[256];
572
573                         ptr += flag;
574                         _D("parsing app_path: EXEC - %s\n", exe);
575
576                         do {
577                                 flag = __parser(ptr, key, sizeof(key));
578                                 if (flag <= 0)
579                                         break;
580                                 ptr += flag;
581
582                                 flag = __parser(ptr, value, sizeof(value));
583                                 if (flag < 0)
584                                         break;
585                                 ptr += flag;
586
587                                 /*bundle_del(kb, key);*/
588                                 bundle_add(kb, key, value);
589                         } while (flag > 0);
590                 } else if (flag == 0) {
591                         _D("parsing app_path: No arguments\n");
592                 } else {
593                         _D("parsing app_path: Invalid argument\n");
594                 }
595         }
596 }
597
598 int __send_to_sigkill(int pid)
599 {
600         int pgid;
601
602         pgid = getpgid(pid);
603         if (pgid <= 1)
604                 return -1;
605
606         if (killpg(pgid, SIGKILL) < 0)
607                 return -1;
608
609         return 0;
610 }
611
612 int __term_app(int pid)
613 {
614         int dummy;
615         if (__app_send_raw
616             (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
617                 _D("terminate packet send error - use SIGKILL");
618                 if (__send_to_sigkill(pid) < 0) {
619                         _E("fail to killing - %d\n", pid);
620                         return -1;
621                 }
622         }
623         _D("term done\n");
624         return 0;
625 }
626
627 static int __get_caller_pid(bundle *kb)
628 {
629         const char *pid_str;
630         int pid;
631
632         pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
633         if(pid_str)
634                 goto end;
635
636         pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
637         if (pid_str == NULL)
638                 return -1;
639
640 end:
641         pid = atoi(pid_str);
642         if (pid <= 1)
643                 return -1;
644
645         return pid;
646 }
647
648 int __foward_cmd(int cmd, bundle *kb, int cr_pid)
649 {
650         int pid;
651         char tmp_pid[MAX_PID_STR_BUFSZ];
652         int datalen;
653         bundle_raw *kb_data;
654         int res;
655
656         if ((pid = __get_caller_pid(kb)) < 0)
657                         return AUL_R_ERROR;
658
659         snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
660
661         bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
662
663         bundle_encode(kb, &kb_data, &datalen);
664         if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0)
665                 res = AUL_R_ERROR;
666
667         free(kb_data);
668
669         return res;
670 }
671
672 void __real_send(int clifd, int ret)
673 {
674         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
675                 if (errno == EPIPE) {
676                         _E("send failed due to EPIPE.\n");
677                 }
678                 _E("send fail to client");
679         }
680
681         close(clifd);
682 }
683
684 void __send_result_to_caller(int clifd, int ret)
685 {
686         char *cmdline;
687         int wait_count;
688         int cmdline_changed = 0;
689         int cmdline_exist = 0;
690
691         if (clifd == -1)
692                 return;
693
694         if (ret <= 1) {
695                 __real_send(clifd, ret);
696                 return;
697         }
698         /* check normally was launched?*/
699         wait_count = 1;
700         do {
701                 cmdline = __proc_get_cmdline_bypid(ret);
702                 if (cmdline == NULL) {
703                         _E("error founded when being launched with %d", ret);
704
705                 } else if (strcmp(cmdline, launchpad_cmdline)) {
706                         free(cmdline);
707                         cmdline_changed = 1;
708                         break;
709                 } else {
710                         cmdline_exist = 1;
711                         free(cmdline);
712                 }
713
714                 _D("-- now wait to change cmdline --");
715                 usleep(50 * 1000);      /* 50ms sleep*/
716                 wait_count++;
717         } while (wait_count <= 20);     /* max 50*20ms will be sleep*/
718
719         if ((!cmdline_exist) && (!cmdline_changed)) {
720                 _E("abnormally launched");
721                 __real_send(clifd, -1); /* abnormally launched*/
722                 return;
723         }
724
725         if (!cmdline_changed)
726                 _E("process launched, but cmdline not changed");
727
728         __real_send(clifd, ret);
729         return;
730 }
731
732 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
733         const char *pkgname, bundle *kb)
734 {
735         app_info_from_db *menu_info;
736
737         menu_info = calloc(1, sizeof(app_info_from_db));
738         if (menu_info == NULL) {
739                 return NULL;
740         }
741
742         menu_info->pkg_name = strdup(pkgname);
743         menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
744         if (menu_info->app_path != NULL)
745                 menu_info->original_app_path = strdup(menu_info->app_path);
746         menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
747         menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
748
749         if (!_get_app_path(menu_info)) {
750                 _free_app_info_from_db(menu_info);
751                 return NULL;
752         }
753
754         return menu_info;
755 }
756
757 /**
758  * free after use it
759  */
760 int get_native_appid(const char* app_path, char** appid) {
761         int rc = smack_lgetlabel(app_path, appid, SMACK_LABEL_ACCESS);
762
763         if (rc != 0 || *appid == NULL) {
764                 _E("smack_lgetlabel fail");
765                 return -1;
766         }
767
768         if (strlen(*appid) != APPID_LEN) {
769                 _E("wrong native appid : %s", *appid);
770                 return -1;
771         }
772
773         if (strlen(app_path) < sizeof(PATH_NATIVE_APP)+APPID_LEN-1) {
774                 _E("wrong native app_path : %s", app_path);
775                 return -1;
776         }
777         else if ( strncmp(app_path, PATH_NATIVE_APP, sizeof(PATH_NATIVE_APP)-1)
778                 || strncmp(&app_path[sizeof(PATH_NATIVE_APP)-1]
779                 , *appid,APPID_LEN) )
780         {
781                 _E("wrong native app_path : %s", app_path);
782                 return -1;
783         }
784         
785         _D("get_appid return : %s", *appid);
786         return 0;
787 }
788
789 int apply_smack_rules(const char* subject, const char* object
790         , const char* access_type)
791 {
792         struct smack_accesses *rules = NULL;
793
794         _D("apply_smack_rules : %s %s %s", subject, object, access_type);
795
796         if (smack_accesses_new(&rules)) {
797                 _E("smack_accesses_new fail");
798                 return -1;
799         }
800
801         if (smack_accesses_add(rules, subject, object, access_type)) {
802                 smack_accesses_free(rules);
803                 _E("smack_accesses_add fail");
804                 return -1;
805         }
806
807         if (smack_accesses_apply(rules)) {
808                 smack_accesses_free(rules);
809                 _E("smack_accesses_apply fail");
810                 return -1;
811         }
812
813         smack_accesses_free(rules);
814
815         return 0;
816 }
817
818 int __prepare_valgrind_outputfile(bundle *kb)
819 {
820         const char *str = NULL;
821         const char **str_array = NULL;
822         int len = 0;
823         int i;
824
825         if(bundle_get_type(kb, DLP_K_VALGRIND_ARG) & BUNDLE_TYPE_ARRAY) {
826                 str_array = bundle_get_str_array(kb, DLP_K_VALGRIND_ARG, &len);
827         } else {
828                 str = bundle_get_val(kb, DLP_K_VALGRIND_ARG);
829                 if(str) {
830                         str_array = &str;
831                         len = 1;
832                 }
833         }
834         if(str_array == NULL) return 0;
835
836         for (i = 0; i < len; i++) {
837                 if(str_array[i] == NULL) break;
838                 /* valgrind log file option */
839                 if (strncmp(str_array[i], OPT_VALGRIND_LOGFILE
840                         , strlen(OPT_VALGRIND_LOGFILE)) == 0)
841                 {
842                         if(strncmp(str_array[i], OPT_VALGRIND_LOGFILE_FIXED
843                                 , strlen(str_array[i])))
844                         {
845                                 _E("wrong valgrind option(%s). It should be %s"
846                                         , str_array[i]
847                                         , OPT_VALGRIND_LOGFILE_FIXED);
848                                 return 1;
849                         }else{
850                                 poll_outputfile |= POLL_VALGRIND_LOGFILE;
851                                 if(remove(PATH_VALGRIND_LOGFILE)){
852                                         _D("cannot remove %s"
853                                                 , PATH_VALGRIND_LOGFILE);
854                                 }
855                         }
856                 }
857                 /* valgrind xml file option */
858                 else if (strncmp(str_array[i], OPT_VALGRIND_XMLFILE
859                         , strlen(OPT_VALGRIND_XMLFILE)) == 0)
860                 {
861                         if(strncmp(str_array[i], OPT_VALGRIND_XMLFILE_FIXED
862                                 , strlen(str_array[i])))
863                         {
864                                 _E("wrong valgrind option(%s). It should be %s"
865                                         , str_array[i]
866                                         , OPT_VALGRIND_XMLFILE_FIXED);
867                                 return 1;
868                         }else{
869                                 poll_outputfile |= POLL_VALGRIND_XMLFILE;
870                                 if(remove(PATH_VALGRIND_XMLFILE)){
871                                         _D("cannot remove %s"
872                                                 , PATH_VALGRIND_XMLFILE);
873                                 }
874                         }
875                 }
876         }
877         return 0;
878 }
879
880 int __prepare_fork(bundle *kb, char *appid)
881 {
882         const char *str = NULL;
883         const char **str_array = NULL;
884         int len = 0;
885         int i;
886
887         poll_outputfile = 0;
888         if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
889                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
890         } else {
891                 str = bundle_get_val(kb, AUL_K_SDK);
892                 if(str) {
893                         str_array = &str;
894                         len = 1;
895                 }
896         }
897         if(str_array == NULL) return 0;
898
899         for (i = 0; i < len; i++) {
900                 if(str_array[i] == NULL) break;
901                 /* gdbserver */
902                 if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
903                 {
904                         if(apply_smack_rules("sdbd",appid,"w")) {
905                                 _E("unable to set sdbd rules");
906                                 return 1;
907                         }
908
909                         // FIXME: set gdbfolder to 755 also
910                         if(dlp_chmod(PATH_GDBSERVER
911                                 , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP
912                                 |S_IROTH|S_IXOTH
913                                 , 1))
914                         {
915                                 _D("unable to set 755 to %s", PATH_GDBSERVER);
916                         }
917                 }
918                 /* valgrind */
919                 else if (strncmp(str_array[i], SDK_VALGRIND
920                         , strlen(str_array[i])) == 0)
921                 {
922                         if (__prepare_valgrind_outputfile(kb)) return 1;
923                 }
924         }
925         return 0;
926 }
927
928 /* chmod and chsmack to read file without root privilege */
929 void __chmod_chsmack_toread(const char * path)
930 {
931         /* chmod */
932         if(dlp_chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 0))
933         {
934                 _E("unable to set 644 to %s", path);
935         }else{
936                 _D("set 644 to %s", path);
937         }
938
939         /* chsmack */
940         if(smack_setlabel(path, "*", SMACK_LABEL_ACCESS))
941         {
942                 _E("failed chsmack -a \"*\" %s", path);
943         }else{
944                 _D("chsmack -a \"*\" %s", path);
945         }
946
947         return;
948 }
949
950 /* waiting for creating outputfile by child process */
951 void __waiting_outputfile()
952 {
953         int wait_count = 0;
954         while(poll_outputfile && wait_count<10) {
955                 /* valgrind log file */
956                 if( (poll_outputfile & POLL_VALGRIND_LOGFILE) 
957                         && (access(PATH_VALGRIND_LOGFILE,F_OK)==0) )
958                 {
959                         __chmod_chsmack_toread(PATH_VALGRIND_LOGFILE);
960                         poll_outputfile &= ~POLL_VALGRIND_LOGFILE;
961                 }
962
963                 /* valgrind xml file */
964                 if( (poll_outputfile & POLL_VALGRIND_XMLFILE)
965                         && (access(PATH_VALGRIND_XMLFILE,F_OK)==0) )
966                 {
967                         __chmod_chsmack_toread(PATH_VALGRIND_XMLFILE);
968                         poll_outputfile &= ~POLL_VALGRIND_XMLFILE;
969                 }
970                 
971                 if(poll_outputfile) {
972                         _D("-- now wait for creating the file --");
973                         usleep(50 * 1000);      /* 50ms sleep*/
974                         wait_count++;
975                 }
976         }
977
978         if(wait_count==10) _E("faild to waiting");
979         return;
980 }
981
982 int __stdout_stderr_redirection(int defpid)
983 {
984         char defpath[UNIX_PATH_MAX];
985         int deffd, result=0; 
986
987         /* stdout */
988         snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/1", defpid);
989         deffd = open(defpath,O_WRONLY);
990         if(deffd < 0) {
991                 _E("opening caller(%d) stdout failed due to %s"
992                         , defpid, strerror(errno));
993                 result++;
994         }else{
995                 dup2(deffd, 1);
996                 close(deffd);
997         }
998
999         /* stderr */
1000         snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/2", defpid);
1001         deffd = open(defpath,O_WRONLY);
1002         if(deffd < 0) {
1003                 _E("opening caller(%d) stderr failed due to %s"
1004                         , defpid,strerror(errno));
1005                 result+=2;
1006         }else{
1007                 dup2(deffd, 2);
1008                 close(deffd);
1009         }
1010
1011         return result;
1012 }
1013
1014 void __launchpad_main_loop(int main_fd)
1015 {
1016         bundle *kb = NULL;
1017         app_pkt_t *pkt = NULL;
1018         app_info_from_db *menu_info = NULL;
1019
1020         const char *pkg_name = NULL;
1021         const char *app_path = NULL;
1022         int pid = -1;
1023         int clifd = -1;
1024         struct ucred cr;
1025         int is_real_launch = 0;
1026
1027         char sock_path[UNIX_PATH_MAX] = {0,};
1028         char * appid = NULL;
1029
1030         pkt = __app_recv_raw(main_fd, &clifd, &cr);
1031         if (!pkt) {
1032                 _D("packet is NULL");
1033                 goto end;
1034         }
1035
1036         kb = bundle_decode(pkt->data, pkt->len);
1037         if (!kb) {
1038                 _D("bundle decode error");
1039                 goto end;
1040         }
1041
1042         INIT_PERF(kb);
1043         PERF("packet processing start");
1044
1045         pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
1046         _D("pkg name : %s\n", pkg_name);
1047
1048         menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
1049         if (menu_info == NULL) {
1050                 _D("such pkg no found");
1051                 goto end;
1052         }
1053
1054         app_path = _get_app_path(menu_info);
1055         if(app_path == NULL) {
1056                 _E("app_path is NULL");
1057                 goto end;
1058         }
1059         if (app_path[0] != '/') {
1060                 _D("app_path is not absolute path");
1061                 goto end;
1062         }
1063
1064         {
1065                 int rc = get_native_appid(app_path,&appid);
1066                 if(rc!=0 || appid==NULL) {
1067                         _E("unable to get native appid");
1068                         if(appid) free(appid);
1069                         goto end;
1070                 }
1071         }
1072
1073         __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
1074         pkg_name = _get_pkgname(menu_info);
1075
1076         PERF("get package information & modify bundle done");
1077
1078         if(__prepare_fork(kb,appid)) goto end;
1079
1080         pid = fork();
1081         if (pid == 0) {
1082                 PERF("fork done");
1083                 _D("lock up test log(no error) : fork done");
1084
1085                 close(clifd);
1086                 close(main_fd);
1087                 __signal_unset_sigchld();
1088                 __signal_fini();
1089
1090                 snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX
1091                         , getpid());
1092                 unlink(sock_path);
1093
1094                 if(__stdout_stderr_redirection(__get_caller_pid(kb))) {
1095                         _E("__stdout_stderr_redirection fail");
1096                 }
1097
1098                 PERF("prepare exec - first done");
1099                 _D("lock up test log(no error) : prepare exec - first done");
1100
1101                 if (__prepare_exec(pkg_name, app_path,
1102                                    menu_info, kb) < 0) {
1103                         _E("preparing work fail to launch - "
1104                            "can not launch %s\n", pkg_name);
1105                         exit(-1);
1106                 }
1107
1108                 PERF("prepare exec - second done");
1109                 _D("lock up test log(no error) : prepare exec - second done");
1110
1111                 __real_launch(app_path, kb);
1112
1113                 exit(-1);
1114         }
1115
1116         _D("==> real launch pid : %d %s\n", pid, app_path);
1117         is_real_launch = 1;
1118
1119  end:
1120         __send_result_to_caller(clifd, pid);
1121
1122         if (pid > 0) {
1123                 if (is_real_launch) {
1124                         /*TODO: retry*/
1125                         __signal_block_sigchld();
1126                         __send_app_launch_signal(pid);
1127                         __signal_unblock_sigchld();
1128                 }
1129         }
1130
1131         if (menu_info != NULL)
1132                 _free_app_info_from_db(menu_info);
1133
1134         if (kb != NULL)
1135                 bundle_free(kb);
1136         if (pkt != NULL)
1137                 free(pkt);
1138         if (appid != NULL) 
1139                 free(appid);
1140
1141         /* Active Flusing for Daemon */
1142         if (initialized > AUL_POLL_CNT) {
1143                 sqlite3_release_memory(SQLITE_FLUSH_MAX);
1144                 malloc_trim(0);
1145                 initialized = 1;
1146         }
1147
1148         if(poll_outputfile) __waiting_outputfile();
1149 }
1150
1151 int __launchpad_pre_init(int argc, char **argv)
1152 {
1153         int fd;
1154
1155         /* signal init*/
1156         __signal_init();
1157
1158         /* get my(launchpad) command line*/
1159         launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
1160         if (launchpad_cmdline == NULL) {
1161                 _E("launchpad cmdline fail to get");
1162                 return -1;
1163         }
1164         _D("launchpad cmdline = %s", launchpad_cmdline);
1165
1166         /* create launchpad sock        */
1167         fd = __create_server_sock(DEBUG_LAUNCHPAD_PID);
1168         if (fd < 0) {
1169                 _E("server sock error");
1170                 return -1;
1171         }
1172
1173         __preload_init(argc, argv);
1174
1175         __preexec_init(argc, argv);
1176
1177         return fd;
1178 }
1179
1180 int __launchpad_post_init()
1181 {
1182         /* Setting this as a global variable to keep track 
1183         of launchpad poll cnt */
1184         /* static int initialized = 0;*/
1185
1186         if (initialized) {
1187                 initialized++;
1188                 return 0;
1189         }
1190
1191         if (__signal_set_sigchld() < 0)
1192                 return -1;
1193
1194         initialized++;
1195
1196         return 0;
1197 }
1198
1199 int main(int argc, char **argv)
1200 {
1201         int main_fd;
1202         struct pollfd pfds[POLLFD_MAX];
1203         int i;
1204
1205         /* init without concerning X & EFL*/
1206         main_fd = __launchpad_pre_init(argc, argv);
1207         if (main_fd < 0) {
1208                 _E("launchpad pre init failed");
1209                 exit(-1);
1210         }
1211
1212         pfds[0].fd = main_fd;
1213         pfds[0].events = POLLIN;
1214         pfds[0].revents = 0;
1215
1216         while (1) {
1217                 if (poll(pfds, POLLFD_MAX, -1) < 0)
1218                         continue;
1219
1220                 /* init with concerning X & EFL (because of booting 
1221                 sequence problem)*/
1222                 if (__launchpad_post_init() < 0) {
1223                         _E("launcpad post init failed");
1224                         exit(-1);
1225                 }
1226
1227                 for (i = 0; i < POLLFD_MAX; i++) {
1228                         if ((pfds[i].revents & POLLIN) != 0) {
1229                                 __launchpad_main_loop(pfds[i].fd);
1230                         }
1231                 }
1232         }
1233 }
1234