Initialize Tizen 2.3
[framework/appfw/aul-1.git] / launchpad_src / launchpad.c
1 /*
2  *  aul
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 /*
24  * simple AUL daemon - launchpad
25  */
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <dlfcn.h>
30 #include <X11/Xlib.h>
31 #include <sys/types.h>
32 #include <signal.h>
33 #include <dirent.h>
34 #include <fcntl.h>
35 #include <stdlib.h>
36 #include <sys/wait.h>
37 #include <poll.h>
38 #include <sys/prctl.h>
39 #include <malloc.h>
40
41 #include "app_sock.h"
42 #include "aul.h"
43
44 #include "config.h"
45
46 #include "menu_db_util.h"
47 #include "simple_util.h"
48 #include "access_control.h"
49 #include "preload.h"
50 #include "preexec.h"
51 #include "perf.h"
52 #include "sigchild.h"
53 #include "aul_util.h"
54
55 #include "heap_dbg.h"
56
57 #include "util_x.h"
58
59 #include "gl.h"
60
61 #include <sqlite3.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
69
70 static char *launchpad_cmdline;
71 static char *__appid = NULL;
72 static int initialized = 0;
73
74 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb);
75 _static_ int __prepare_exec(const char *pkg_name,
76                             const char *app_path, app_info_from_db * menu_info,
77                             bundle * kb);
78 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb);
79 _static_ char **__create_argc_argv(bundle * kb, int *margc);
80 _static_ int __normal_fork_exec(int argc, char **argv);
81 _static_ void __real_launch(const char *app_path, bundle * kb);
82 static inline int __parser(const char *arg, char *out, int out_size);
83 _static_ void __modify_bundle(bundle * kb, int caller_pid,
84                             app_info_from_db * menu_info, int cmd);
85 _static_ int __child_raise_win_by_x(int pid, void *priv);
86 _static_ int __raise_win_by_x(int pid);
87 _static_ int __send_to_sigkill(int pid);
88 _static_ int __term_app(int pid);
89 _static_ int __resume_app(int pid);
90 _static_ int __real_send(int clifd, int ret);
91 _static_ void __send_result_to_caller(int clifd, int ret);
92 _static_ void __launchpad_main_loop(int main_fd);
93 _static_ int __launchpad_pre_init(int argc, char **argv);
94 _static_ int __launchpad_post_init();
95
96 extern ail_error_e ail_db_close(void);
97
98
99
100
101 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
102 {
103         const char *str;
104
105         setenv("PKG_NAME", _get_pkgname(menu_info), 1);
106
107         USE_ENGINE("gl")
108
109         str = bundle_get_val(kb, AUL_K_STARTTIME);
110         if (str != NULL)
111                 setenv("APP_START_TIME", str, 1);
112
113         if (menu_info->hwacc != NULL)
114                 setenv("HWACC", menu_info->hwacc, 1);
115         if (menu_info->taskmanage != NULL)
116                 setenv("TASKMANAGE", menu_info->taskmanage, 1);
117 }
118
119 _static_ int __prepare_exec(const char *pkg_name,
120                             const char *app_path, app_info_from_db * menu_info,
121                             bundle * kb)
122 {
123         char *file_name;
124         char process_name[AUL_PR_NAME];
125         int ret;
126
127         /* Set new session ID & new process group ID*/
128         /* In linux, child can set new session ID without check permission */
129         /* TODO : should be add to check permission in the kernel*/
130         setsid();
131
132         __preexec_run(menu_info->pkg_type, pkg_name, app_path);
133
134         /* SET PRIVILEGES*/
135         if(bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) {
136                  _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name, menu_info->pkg_type, app_path);
137                 if ((ret = __set_access(pkg_name, menu_info->pkg_type, app_path)) < 0) {
138                          _D("fail to set privileges - check your package's credential : %d\n", ret);
139                         return -1;
140                 }
141         }
142
143         /* SET DUMPABLE - for coredump*/
144         prctl(PR_SET_DUMPABLE, 1);
145
146         /* SET PROCESS NAME*/
147         if (app_path == NULL) {
148                 _D("app_path should not be NULL - check menu db");
149                 return -1;
150         }
151         file_name = strrchr(app_path, '/') + 1;
152         if (file_name == NULL) {
153                 _D("can't locate file name to execute");
154                 return -1;
155         }
156         memset(process_name, '\0', AUL_PR_NAME);
157         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
158         prctl(PR_SET_NAME, process_name);
159
160         /* SET ENVIROMENT*/
161         __set_env(menu_info, kb);
162
163         return 0;
164 }
165
166 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb)
167 {
168         int datalen;
169         int ret;
170         bundle_raw *kb_data;
171
172         bundle_encode(kb, &kb_data, &datalen);
173         if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
174                 _E("error request fake launch - error code = %d", ret);
175         free(kb_data);
176         return ret;
177 }
178
179 _static_ char **__create_argc_argv(bundle * kb, int *margc)
180 {
181         char **argv;
182         int argc;
183
184         argc = bundle_export_to_argv(kb, &argv);
185
186         *margc = argc;
187         return argv;
188 }
189
190 _static_ int __normal_fork_exec(int argc, char **argv)
191 {
192         _D("start real fork and exec\n");
193
194         if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
195                 if (errno == EACCES)
196                         _E("such a file is no executable - %s", argv[0]);
197                 else
198                         _E("unknown executable error - %s", argv[0]);
199                 return -1;
200         }
201         /* never reach*/
202         return 0;
203 }
204
205 _static_ void __real_launch(const char *app_path, bundle * kb)
206 {
207         int app_argc;
208         char **app_argv;
209         int i;
210
211         app_argv = __create_argc_argv(kb, &app_argc);
212         app_argv[0] = strdup(app_path);
213
214         for (i = 0; i < app_argc; i++) {
215                 if( (i%2) == 1)
216                         continue;
217                 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
218         }
219
220         PERF("setup argument done");
221
222         /* Temporary log: launch time checking */
223         SECURE_LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
224
225         __preload_exec(app_argc, app_argv);
226
227         __normal_fork_exec(app_argc, app_argv);
228 }
229
230
231 /*
232  * Parsing original app path to retrieve default bundle
233  *
234  * -1 : Invalid sequence
235  * -2 : Buffer overflow
236  *
237  */
238 static inline int __parser(const char *arg, char *out, int out_size)
239 {
240         register int i;
241         int state = 1;
242         char *start_out = out;
243
244         if (arg == NULL || out == NULL) {
245                 /* Handles null buffer*/
246                 return 0;
247         }
248
249         for (i = 0; out_size > 1; i++) {
250                 switch (state) {
251                 case 1:
252                         switch (arg[i]) {
253                         case ' ':
254                         case '\t':
255                                 state = 5;
256                                 break;
257                         case '\0':
258                                 state = 7;
259                                 break;
260                         case '\"':
261                                 state = 2;
262                                 break;
263                         case '\\':
264                                 state = 4;
265                                 break;
266                         default:
267                                 *out = arg[i];
268                                 out++;
269                                 out_size--;
270                                 break;
271                         }
272                         break;
273                 case 2: /* escape start*/
274                         switch (arg[i]) {
275                         case '\0':
276                                 state = 6;
277                                 break;
278                         case '\"':
279                                 state = 1;
280                                 break;
281                         default:
282                                 *out = arg[i];
283                                 out++;
284                                 out_size--;
285                                 break;
286                         }
287                         break;
288                 case 4: /* character escape*/
289                         if (arg[i] == '\0') {
290                                 state = 6;
291                         } else {
292                                 *out = arg[i];
293                                 out++;
294                                 out_size--;
295                                 state = 1;
296                         }
297                         break;
298                 case 5: /* token*/
299                         if (out != start_out) {
300                                 *out = '\0';
301                                 out_size--;
302                                 return i;
303                         }
304                         i--;
305                         state = 1;
306                         break;
307                 case 6:
308                         return -1;      /* error*/
309                 case 7: /* terminate*/
310                         *out = '\0';
311                         out_size--;
312                         return 0;
313                 default:
314                         state = 6;
315                         break;  /* error*/
316                 }
317         }
318
319         if (out_size == 1) {
320                 *out = '\0';
321         }
322         /* Buffer overflow*/
323         return -2;
324 }
325
326 _static_ void __modify_bundle(bundle * kb, int caller_pid,
327                             app_info_from_db * menu_info, int cmd)
328 {
329         bundle_del(kb, AUL_K_PKG_NAME);
330         bundle_del(kb, AUL_K_EXEC);
331         bundle_del(kb, AUL_K_PACKAGETYPE);
332         bundle_del(kb, AUL_K_HWACC);
333         bundle_del(kb, AUL_K_TASKMANAGE);
334
335         /* Parse app_path to retrieve default bundle*/
336         if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_START_ASYNC || cmd == APP_OPEN || cmd == APP_RESUME) {
337                 char *ptr;
338                 char exe[MAX_PATH_LEN];
339                 int flag;
340
341                 ptr = _get_original_app_path(menu_info);
342
343                 flag = __parser(ptr, exe, sizeof(exe));
344                 if (flag > 0) {
345                         char key[256];
346                         char value[256];
347
348                         ptr += flag;
349                         SECURE_LOGD("parsing app_path: EXEC - %s\n", exe);
350
351                         do {
352                                 flag = __parser(ptr, key, sizeof(key));
353                                 if (flag <= 0)
354                                         break;
355                                 ptr += flag;
356
357                                 flag = __parser(ptr, value, sizeof(value));
358                                 if (flag < 0)
359                                         break;
360                                 ptr += flag;
361
362                                 /*bundle_del(kb, key);*/
363                                 bundle_add(kb, key, value);
364                         } while (flag > 0);
365                 } else if (flag == 0) {
366                         _D("parsing app_path: No arguments\n");
367                 } else {
368                         _D("parsing app_path: Invalid argument\n");
369                 }
370         }
371 }
372
373 _static_ int __child_raise_win_by_x(int pid, void *priv)
374 {
375         return x_util_raise_win(pid);
376 }
377
378 _static_ int __raise_win_by_x(int pid)
379 {
380         int pgid;
381         if (x_util_raise_win(pid) == 0)
382                 return 0;
383
384         /* support app launched by shell script*/
385         pgid = getpgid(pid);
386         _D("X raise failed. try to find first child & raise it - c:%d p:%d\n",
387            pgid, pid);
388
389         if (pgid <= 1)
390                 return -1;
391         if (__proc_iter_pgid(pgid, __child_raise_win_by_x, NULL) < 0)
392                 return -1;
393
394         return 0;
395 }
396
397 _static_ int __send_to_sigkill(int pid)
398 {
399         int pgid;
400
401         pgid = getpgid(pid);
402         if (pgid <= 1)
403                 return -1;
404
405         if (killpg(pgid, SIGKILL) < 0)
406                 return -1;
407
408         return 0;
409 }
410
411 _static_ int __term_app(int pid)
412 {
413         int dummy;
414         if (__app_send_raw
415             (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
416                 _D("terminate packet send error - use SIGKILL");
417                 if (__send_to_sigkill(pid) < 0) {
418                         _E("fail to killing - %d\n", pid);
419                         return -1;
420                 }
421         }
422         _D("term done\n");
423         return 0;
424 }
425
426 _static_ int __resume_app(int pid)
427 {
428         int dummy;
429         int ret;
430         if ((ret =
431              __app_send_raw(pid, APP_RESUME_BY_PID, (unsigned char *)&dummy,
432                             sizeof(int))) < 0) {
433                 if (ret == -EAGAIN)
434                         _E("resume packet timeout error");
435                 else {
436                         _D("resume packet send error - use raise win");
437                         if (__raise_win_by_x(pid) < 0) {
438                                 _E("raise failed - %d resume fail\n", pid);
439                                 _E("we will term the app - %d\n", pid);
440                                 __send_to_sigkill(pid);
441                                 ret = -1;
442                         } else
443                                 ret = 0;
444                 }
445         }
446         _D("resume done\n");
447         return ret;
448 }
449
450 static int __get_caller_pid(bundle *kb)
451 {
452         const char *pid_str;
453         int pid;
454
455         pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
456         if(pid_str)
457                 goto end;
458
459         pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
460         if (pid_str == NULL)
461                 return -1;
462
463 end:
464         pid = atoi(pid_str);
465         if (pid <= 1)
466                 return -1;
467
468         return pid;
469 }
470
471 _static_ int __foward_cmd(int cmd, bundle *kb, int cr_pid)
472 {
473         int pid;
474         char tmp_pid[MAX_PID_STR_BUFSZ];
475         int datalen;
476         bundle_raw *kb_data;
477         int res;
478
479         if ((pid = __get_caller_pid(kb)) < 0)
480                         return AUL_R_ERROR;
481
482         snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
483
484         bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
485
486         bundle_encode(kb, &kb_data, &datalen);
487         if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0)
488                 res = AUL_R_ERROR;
489
490         free(kb_data);
491
492         return res;
493 }
494
495 _static_ int __real_send(int clifd, int ret)
496 {
497         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
498                 if (errno == EPIPE) {
499                         _E("send failed due to EPIPE.\n");
500                         close(clifd);
501                         return -1;
502                 }
503                 _E("send fail to client");
504         }
505
506         close(clifd);
507         return 0;
508 }
509
510 _static_ void __send_result_to_caller(int clifd, int ret)
511 {
512         char *cmdline;
513         int wait_count;
514         int cmdline_changed = 0;
515         int cmdline_exist = 0;
516         int r;
517
518         if (clifd == -1)
519                 return;
520
521         if (ret <= 1) {
522                 __real_send(clifd, ret);
523                 return;
524         }
525         /* check normally was launched?*/
526         wait_count = 1;
527         do {
528                 cmdline = __proc_get_cmdline_bypid(ret);
529                 if (cmdline == NULL) {
530                         _E("error founded when being launched with %d", ret);
531
532                 } else if (strcmp(cmdline, launchpad_cmdline)) {
533                         free(cmdline);
534                         cmdline_changed = 1;
535                         break;
536                 } else {
537                         cmdline_exist = 1;
538                         free(cmdline);
539                 }
540
541                 _D("-- now wait to change cmdline --");
542                 usleep(100 * 1000);     /* 100ms sleep*/
543                 wait_count++;
544         } while (wait_count <= 20);     /* max 100*20ms will be sleep*/
545
546         if ((!cmdline_exist) && (!cmdline_changed)) {
547                 __real_send(clifd, -1); /* abnormally launched*/
548                 return;
549         }
550
551         if (!cmdline_changed)
552                 _E("process launched, but cmdline not changed");
553
554         if(__real_send(clifd, ret) < 0) {
555                 r = kill(ret, SIGKILL);
556                 if (r == -1)
557                         _E("send SIGKILL: %s", strerror(errno));
558         }
559
560         return;
561 }
562
563 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
564                                                         const char *pkgname, bundle *kb)
565 {
566         app_info_from_db *menu_info;
567
568         menu_info = calloc(1, sizeof(app_info_from_db));
569         if (menu_info == NULL) {
570                 return NULL;
571         }
572
573         menu_info->pkg_name = strdup(pkgname);
574         menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
575         if (menu_info->app_path != NULL)
576                 menu_info->original_app_path = strdup(menu_info->app_path);
577         menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
578         menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
579         menu_info->taskmanage = strdup(bundle_get_val(kb, AUL_K_TASKMANAGE));
580
581         if (!_get_app_path(menu_info)) {
582                 _free_app_info_from_db(menu_info);
583                 return NULL;
584         }
585
586         return menu_info;
587 }
588
589 static void __release_appid_at_exit(void)
590 {
591         if (__appid != NULL) {
592                 free(__appid);
593         }
594 }
595
596 _static_ void __launchpad_main_loop(int main_fd)
597 {
598         bundle *kb = NULL;
599         app_pkt_t *pkt = NULL;
600         app_info_from_db *menu_info = NULL;
601
602         const char *pkg_name = NULL;
603         const char *app_path = NULL;
604         int pid = -1;
605         int clifd = -1;
606         struct ucred cr;
607         int is_real_launch = 0;
608
609         char sock_path[UNIX_PATH_MAX] = {0,};
610
611         pkt = __app_recv_raw(main_fd, &clifd, &cr);
612         if (!pkt) {
613                 _D("packet is NULL");
614                 goto end;
615         }
616
617         kb = bundle_decode(pkt->data, pkt->len);
618         if (!kb) {
619                 _D("bundle decode error");
620                 goto end;
621         }
622
623         INIT_PERF(kb);
624         PERF("packet processing start");
625
626         pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
627         SECURE_LOGD("pkg name : %s\n", pkg_name);
628
629         menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
630         if (menu_info == NULL) {
631                 _D("such pkg no found");
632                 goto end;
633         }
634
635         app_path = _get_app_path(menu_info);
636         if(app_path == NULL) {
637                 _E("app_path is NULL");
638                 goto end;
639         }
640         if (app_path[0] != '/') {
641                 _D("app_path is not absolute path");
642                 goto end;
643         }
644
645         __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
646         pkg_name = _get_pkgname(menu_info);
647
648         PERF("get package information & modify bundle done");
649
650         {
651                 pid = fork();
652                 if (pid == 0) {
653                         PERF("fork done");
654                         _D("lock up test log(no error) : fork done");
655
656                         close(clifd);
657                         close(main_fd);
658                         __signal_unset_sigchld();
659                         __signal_fini();
660
661                         snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid());
662                         unlink(sock_path);
663
664                         PERF("prepare exec - first done");
665                         _D("lock up test log(no error) : prepare exec - first done");
666
667                         __appid = strdup(pkg_name);
668                         aul_set_preinit_appid(__appid);
669                         atexit(__release_appid_at_exit);
670
671                         if (__prepare_exec(pkg_name, app_path,
672                                            menu_info, kb) < 0) {
673                                 SECURE_LOGE("preparing work fail to launch - "
674                                    "can not launch %s\n", pkg_name);
675                                 exit(-1);
676                         }
677
678                         PERF("prepare exec - second done");
679                         _D("lock up test log(no error) : prepare exec - second done");
680
681                         __real_launch(app_path, kb);
682
683                         exit(-1);
684                 }
685                 SECURE_LOGD("==> real launch pid : %d %s\n", pid, app_path);
686                 is_real_launch = 1;
687         }
688
689  end:
690         __send_result_to_caller(clifd, pid);
691
692         if (pid > 0) {
693                 if (is_real_launch) {
694                         /*TODO: retry*/
695                         __signal_block_sigchld();
696                         __send_app_launch_signal(pid);
697                         __signal_unblock_sigchld();
698                 }
699         }
700
701         if (menu_info != NULL)
702                 _free_app_info_from_db(menu_info);
703
704         if (kb != NULL)
705                 bundle_free(kb);
706         if (pkt != NULL)
707                 free(pkt);
708
709         /* Active Flusing for Daemon */
710         if (initialized > AUL_POLL_CNT) {
711                 sqlite3_release_memory(SQLITE_FLUSH_MAX);
712                 malloc_trim(0);
713                 initialized = 1;
714         }
715
716 }
717
718 _static_ int __launchpad_pre_init(int argc, char **argv)
719 {
720         int fd;
721
722         /* signal init*/
723         __signal_init();
724
725         /* get my(launchpad) command line*/
726         launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
727         if (launchpad_cmdline == NULL) {
728                 _E("launchpad cmdline fail to get");
729                 return -1;
730         }
731         _D("launchpad cmdline = %s", launchpad_cmdline);
732
733         /* create launchpad sock        */
734         fd = __create_server_sock(LAUNCHPAD_PID);
735         if (fd < 0) {
736                 _E("server sock error");
737                 return -1;
738         }
739
740         __preload_init(argc, argv);
741
742         /* preexec is not used */
743         //__preexec_init(argc, argv);
744
745         return fd;
746 }
747
748 _static_ int __launchpad_post_init()
749 {
750         /* Setting this as a global variable to keep track
751         of launchpad poll cnt */
752         /* static int initialized = 0;*/
753
754         if (initialized) {
755                 initialized++;
756                 return 0;
757         }
758
759         if (__signal_set_sigchld() < 0)
760                 return -1;
761
762         initialized++;
763
764         return 0;
765 }
766
767 int main(int argc, char **argv)
768 {
769         int main_fd;
770         struct pollfd pfds[POLLFD_MAX];
771         int i;
772
773         /* init without concerning X & EFL*/
774         main_fd = __launchpad_pre_init(argc, argv);
775         if (main_fd < 0) {
776                 _E("launchpad pre init failed");
777                 exit(-1);
778         }
779
780         pfds[0].fd = main_fd;
781         pfds[0].events = POLLIN;
782         pfds[0].revents = 0;
783
784         while (1) {
785                 if (poll(pfds, POLLFD_MAX, -1) < 0)
786                         continue;
787
788                 /* init with concerning X & EFL (because of booting
789                 sequence problem)*/
790                 if (__launchpad_post_init() < 0) {
791                         _E("launcpad post init failed");
792                         exit(-1);
793                 }
794
795                 for (i = 0; i < POLLFD_MAX; i++) {
796                         if ((pfds[i].revents & POLLIN) != 0) {
797                                 __launchpad_main_loop(pfds[i].fd);
798                         }
799                 }
800         }
801 }
802