4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 * simple AUL daemon - launchpad
32 #include <sys/types.h>
39 #include <sys/prctl.h>
41 #include <sys/resource.h>
43 #include <bundle_internal.h>
50 #include "menu_db_util.h"
51 #include "simple_util.h"
52 #include "access_control.h"
67 #define _static_ static inline
69 #define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */
70 #define AUL_POLL_CNT 15
71 #define AUL_PR_NAME 16
74 static char *launchpad_cmdline;
75 static char *__appid = NULL;
76 static int initialized = 0;
78 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb);
79 _static_ int __prepare_exec(const char *pkg_name,
80 const char *app_path, app_info_from_db * menu_info,
82 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb);
83 _static_ char **__create_argc_argv(bundle * kb, int *margc);
84 _static_ int __normal_fork_exec(int argc, char **argv);
85 _static_ void __real_launch(const char *app_path, bundle * kb);
86 static inline int __parser(const char *arg, char *out, int out_size);
87 _static_ void __modify_bundle(bundle * kb, int caller_pid,
88 app_info_from_db * menu_info, int cmd);
89 _static_ int __child_raise_win_by_x(int pid, void *priv);
90 _static_ int __raise_win_by_x(int pid);
91 _static_ int __send_to_sigkill(int pid);
92 _static_ int __term_app(int pid);
93 _static_ int __resume_app(int pid);
94 _static_ int __real_send(int clifd, int ret);
95 _static_ void __send_result_to_caller(int clifd, int ret);
96 _static_ void __launchpad_main_loop(int main_fd, int sigchld_fd);
97 _static_ int __launchpad_pre_init(int argc, char **argv);
98 _static_ int __launchpad_post_init();
104 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
108 setenv("PKG_NAME", _get_pkgname(menu_info), 1);
112 str = bundle_get_val(kb, AUL_K_STARTTIME);
114 setenv("APP_START_TIME", str, 1);
116 if (menu_info->hwacc != NULL)
117 setenv("HWACC", menu_info->hwacc, 1);
118 if (menu_info->taskmanage != NULL)
119 setenv("TASKMANAGE", menu_info->taskmanage, 1);
122 _static_ int __prepare_exec(const char *pkg_name,
123 const char *app_path, app_info_from_db * menu_info,
127 char process_name[AUL_PR_NAME];
130 /* Set new session ID & new process group ID*/
131 /* In linux, child can set new session ID without check permission */
132 /* TODO : should be add to check permission in the kernel*/
135 __preexec_run(menu_info->pkg_type, pkg_name, app_path);
138 SECURE_LOGD("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name, menu_info->pkg_type, app_path);
139 if ((ret = __set_access(pkg_name, menu_info->pkg_type, app_path)) < 0) {
140 _D("fail to set privileges - check your package's credential : %d\n", ret);
143 /* SET DUMPABLE - for coredump*/
144 prctl(PR_SET_DUMPABLE, 1);
146 /* SET PROCESS NAME*/
147 if (app_path == NULL) {
148 _D("app_path should not be NULL - check menu db");
151 file_name = strrchr(app_path, '/') + 1;
152 if (file_name == NULL) {
153 _D("can't locate file name to execute");
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);
161 __set_env(menu_info, kb);
166 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb)
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);
179 _static_ char **__create_argc_argv(bundle * kb, int *margc)
184 argc = bundle_export_to_argv(kb, &argv);
190 _static_ int __normal_fork_exec(int argc, char **argv)
192 _D("start real fork and exec\n");
194 #ifdef _APPFW_FEATURE_PRIORITY_CHANGE
195 int res = setpriority(PRIO_PROCESS, 0, 0);
198 SECURE_LOGE("Setting process (%d) priority to 0 failed, errno: %d (%s)",
199 getpid(), errno, strerror(errno));
202 if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
204 _E("such a file is no executable - %s", argv[0]);
206 _E("unknown executable error - %s", argv[0]);
213 _static_ void __real_launch(const char *app_path, bundle * kb)
219 app_argv = __create_argc_argv(kb, &app_argc);
220 app_argv[0] = strdup(app_path);
222 for (i = 0; i < app_argc; i++) {
225 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
228 PERF("setup argument done");
230 /* Temporary log: launch time checking */
231 SECURE_LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
233 __preload_exec(app_argc, app_argv);
235 __normal_fork_exec(app_argc, app_argv);
240 * Parsing original app path to retrieve default bundle
242 * -1 : Invalid sequence
243 * -2 : Buffer overflow
246 static inline int __parser(const char *arg, char *out, int out_size)
250 char *start_out = out;
252 if (arg == NULL || out == NULL) {
253 /* Handles null buffer*/
257 for (i = 0; out_size > 1; i++) {
281 case 2: /* escape start*/
296 case 4: /* character escape*/
297 if (arg[i] == '\0') {
307 if (out != start_out) {
316 return -1; /* error*/
317 case 7: /* terminate*/
334 _static_ void __modify_bundle(bundle * kb, int caller_pid,
335 app_info_from_db * menu_info, int cmd)
337 bundle_del(kb, AUL_K_PKG_NAME);
338 bundle_del(kb, AUL_K_EXEC);
339 bundle_del(kb, AUL_K_PACKAGETYPE);
340 bundle_del(kb, AUL_K_HWACC);
341 bundle_del(kb, AUL_K_TASKMANAGE);
343 /* Parse app_path to retrieve default bundle*/
345 || cmd == APP_START_RES
346 || cmd == APP_START_ASYNC
347 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
348 || cmd == APP_START_MULTI_INSTANCE
354 char exe[MAX_PATH_LEN];
357 ptr = _get_original_app_path(menu_info);
359 flag = __parser(ptr, exe, sizeof(exe));
365 SECURE_LOGD("parsing app_path: EXEC - %s\n", exe);
368 flag = __parser(ptr, key, sizeof(key));
373 flag = __parser(ptr, value, sizeof(value));
378 /*bundle_del(kb, key);*/
379 bundle_add(kb, key, value);
381 } else if (flag == 0) {
382 _D("parsing app_path: No arguments\n");
384 _D("parsing app_path: Invalid argument\n");
389 _static_ int __child_raise_win_by_x(int pid, void *priv)
391 return x_util_raise_win(pid);
394 _static_ int __raise_win_by_x(int pid)
397 if (x_util_raise_win(pid) == 0)
400 /* support app launched by shell script*/
402 _D("X raise failed. try to find first child & raise it - c:%d p:%d\n",
407 if (__proc_iter_pgid(pgid, __child_raise_win_by_x, NULL) < 0)
413 _static_ int __send_to_sigkill(int pid)
421 if (killpg(pgid, SIGKILL) < 0)
427 _static_ int __term_app(int pid)
431 (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
432 _D("terminate packet send error - use SIGKILL");
433 if (__send_to_sigkill(pid) < 0) {
434 _E("fail to killing - %d\n", pid);
442 _static_ int __resume_app(int pid)
447 __app_send_raw(pid, APP_RESUME_BY_PID, (unsigned char *)&dummy,
450 _E("resume packet timeout error");
452 _D("resume packet send error - use raise win");
453 if (__raise_win_by_x(pid) < 0) {
454 _E("raise failed - %d resume fail\n", pid);
455 _E("we will term the app - %d\n", pid);
456 __send_to_sigkill(pid);
466 static int __get_caller_pid(bundle *kb)
471 pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
475 pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
487 _static_ int __foward_cmd(int cmd, bundle *kb, int cr_pid)
490 char tmp_pid[MAX_PID_STR_BUFSZ];
495 if ((pid = __get_caller_pid(kb)) < 0)
498 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
500 bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
502 bundle_encode(kb, &kb_data, &datalen);
503 if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0)
511 _static_ int __real_send(int clifd, int ret)
513 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
514 if (errno == EPIPE) {
515 _E("send failed due to EPIPE.\n");
519 _E("send fail to client");
526 _static_ void __send_result_to_caller(int clifd, int ret)
530 int cmdline_changed = 0;
531 int cmdline_exist = 0;
538 __real_send(clifd, ret);
541 /* check normally was launched?*/
544 cmdline = __proc_get_cmdline_bypid(ret);
545 if (cmdline == NULL) {
546 _E("error founded when being launched with %d", ret);
548 } else if (strcmp(cmdline, launchpad_cmdline)) {
557 _D("-- now wait to change cmdline --");
558 usleep(100 * 1000); /* 100ms sleep*/
560 } while (wait_count <= 20); /* max 100*20ms will be sleep*/
562 if ((!cmdline_exist) && (!cmdline_changed)) {
563 __real_send(clifd, -1); /* abnormally launched*/
567 if (!cmdline_changed)
568 _E("process launched, but cmdline not changed");
570 if(__real_send(clifd, ret) < 0) {
571 r = kill(ret, SIGKILL);
573 _E("send SIGKILL: %s", strerror(errno));
579 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
580 const char *pkgname, bundle *kb)
582 app_info_from_db *menu_info;
584 menu_info = calloc(1, sizeof(app_info_from_db));
585 if (menu_info == NULL) {
589 menu_info->pkg_name = strdup(pkgname);
590 menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
591 if (menu_info->app_path != NULL)
592 menu_info->original_app_path = strdup(menu_info->app_path);
593 menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
594 menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
595 menu_info->taskmanage = strdup(bundle_get_val(kb, AUL_K_TASKMANAGE));
597 if (!_get_app_path(menu_info)) {
598 _free_app_info_from_db(menu_info);
605 static void __release_appid_at_exit(void)
607 if (__appid != NULL) {
612 _static_ void __launchpad_main_loop(int main_fd, int sigchld_fd)
615 app_pkt_t *pkt = NULL;
616 app_info_from_db *menu_info = NULL;
618 const char *pkg_name = NULL;
619 const char *app_path = NULL;
623 int is_real_launch = 0;
625 char sock_path[UNIX_PATH_MAX] = {0,};
627 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "AUL:PAD:MAINLOOP");
628 pkt = __app_recv_raw(main_fd, &clifd, &cr);
630 _D("packet is NULL");
634 kb = bundle_decode(pkt->data, pkt->len);
636 _D("bundle decode error");
641 PERF("packet processing start");
643 pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
644 SECURE_LOGD("pkg name : %s\n", pkg_name);
646 menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
647 if (menu_info == NULL) {
648 _D("such pkg no found");
652 app_path = _get_app_path(menu_info);
653 if(app_path == NULL) {
654 _E("app_path is NULL");
657 if (app_path[0] != '/') {
658 _D("app_path is not absolute path");
662 __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
663 pkg_name = _get_pkgname(menu_info);
665 PERF("get package information & modify bundle done");
671 _D("lock up test log(no error) : fork done");
676 __signal_unblock_sigchld();
679 snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid());
682 PERF("prepare exec - first done");
683 _D("lock up test log(no error) : prepare exec - first done");
685 __appid = strdup(pkg_name);
686 aul_set_preinit_appid(__appid);
687 atexit(__release_appid_at_exit);
689 if (__prepare_exec(pkg_name, app_path,
690 menu_info, kb) < 0) {
691 SECURE_LOGE("preparing work fail to launch - "
692 "can not launch %s\n", pkg_name);
693 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
697 PERF("prepare exec - second done");
698 _D("lock up test log(no error) : prepare exec - second done");
700 __real_launch(app_path, kb);
702 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
705 SECURE_LOGD("==> real launch pid : %d %s\n", pid, app_path);
710 __send_result_to_caller(clifd, pid);
714 __send_app_launch_signal(pid);
717 if (menu_info != NULL)
718 _free_app_info_from_db(menu_info);
725 /* Active Flusing for Daemon */
726 if (initialized > AUL_POLL_CNT) {
727 sqlite3_release_memory(SQLITE_FLUSH_MAX);
732 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
736 _static_ int __launchpad_pre_init(int argc, char **argv)
743 /* get my(launchpad) command line*/
744 launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
745 if (launchpad_cmdline == NULL) {
746 _E("launchpad cmdline fail to get");
749 _D("launchpad cmdline = %s", launchpad_cmdline);
751 /* create launchpad sock */
752 fd = __create_server_sock(LAUNCHPAD_PID);
754 _E("server sock error");
758 __preload_init(argc, argv);
760 // __preexec_init(argc, argv);
765 _static_ int __launchpad_post_init()
767 /* Setting this as a global variable to keep track
768 of launchpad poll cnt */
769 /* static int initialized = 0;*/
781 int main(int argc, char **argv)
785 struct pollfd pfds[POLLFD_MAX];
787 /* init without concerning X & EFL*/
788 main_fd = __launchpad_pre_init(argc, argv);
790 _E("launchpad pre init failed");
794 pfds[0].fd = main_fd;
795 pfds[0].events = POLLIN;
798 sigchld_fd = __signal_get_sigchld_fd();
799 if (sigchld_fd == -1) {
800 _E("failed to get sigchld fd");
803 pfds[1].fd = sigchld_fd;
804 pfds[1].events = POLLIN;
807 #ifdef _APPFW_FEATURE_PRIORITY_CHANGE
808 int res = setpriority(PRIO_PROCESS, 0, -12);
811 SECURE_LOGE("Setting process (%d) priority to -12 failed, errno: %d (%s)",
812 getpid(), errno, strerror(errno));
816 if (poll(pfds, POLLFD_MAX, -1) < 0)
819 /* init with concerning X & EFL (because of booting
821 if (__launchpad_post_init() < 0) {
822 _E("launcpad post init failed");
826 if ((pfds[1].revents & POLLIN) != 0) {
827 struct signalfd_siginfo siginfo;
831 s = read(pfds[1].fd, &siginfo, sizeof(struct signalfd_siginfo));
835 if (s != sizeof(struct signalfd_siginfo)) {
836 _E("error reading sigchld info");
839 __launchpad_process_sigchld(&siginfo);
843 if ((pfds[0].revents & POLLIN) != 0) {
844 __launchpad_main_loop(pfds[0].fd, sigchld_fd);