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.
26 #include <app-checker-server.h>
30 #include <app2ext_interface.h>
32 #include "amd_config.h"
33 #include "amd_launch.h"
34 #include "amd_appinfo.h"
35 #include "amd_status.h"
37 #include "simple_util.h"
38 #include "amd_cgutil.h"
41 #define TERM_WAIT_SEC 3
44 struct appinfomgr *_laf;
48 char *pkg_name; /* package */
49 char *app_path; /* exec */
50 char *original_app_path; /* exec */
51 int multiple; /* x_slp_multiple */
53 } app_info_from_pkgmgr;
55 static GList *_kill_list;
60 guint tid; /* timer ID */
64 static void _prepare_exec(void)
68 signal(SIGINT, SIG_DFL);
69 signal(SIGTERM, SIG_DFL);
70 signal(SIGCHLD, SIG_DFL);
72 /* TODO: do security job */
76 static int _add_cgroup(struct cginfo *cg, const char *group, int pid)
80 r = cgutil_exist_group(cg, CTRL_MGR, group);
82 _E("exist check error: %s", strerror(errno));
86 if (r == 0) { /* not exist */
87 r = cgutil_create_group(cg, CTRL_MGR, group);
89 _E("create group error");
94 r = cgutil_group_add_pid(cg, CTRL_MGR, group, pid);
96 _E("add pid to group error");
97 cgutil_remove_group(cg, CTRL_MGR, group);
104 static char **__create_argc_argv(bundle * kb, int *margc)
109 argc = bundle_export_to_argv(kb, &argv);
114 static void _do_exec(struct cginfo *cg, const char *cmd, const char *group, bundle *kb)
123 r = _add_cgroup(cg, group, getpid());
127 b = g_shell_parse_argv(cmd, &argc, &argv, NULL);
130 b_argv = __create_argc_argv(kb, &b_argc);
131 b_argv[0] = strdup(argv[0]);
133 execv(b_argv[0], b_argv);
138 execv(argv[0], argv);
141 _E("exec error: %s", strerror(errno));
145 int service_start(struct cginfo *cg, const char *group, const char *cmd, bundle *kb)
150 if (!cg || !group || !*group || !cmd || !*cmd) {
152 _E("service start: %s", strerror(errno));
158 case 0: /* child process */
159 _do_exec(cg, cmd, group, kb);
164 _E("service start: fork: %s", strerror(errno));
167 default: /* parent process */
168 _D("child process: %d", p);
176 int _start_srv(struct appinfo *ai, bundle *kb)
182 group = appinfo_get_filename(ai);
184 cmd = appinfo_get_value(ai, AIT_EXEC);
186 _E("start service: '%s' has no exec", group);
190 r = service_start(_lcg, group, cmd, kb);
192 _E("start service: '%s': failed", group);
199 static void _free_kt(struct ktimer *kt)
204 cgutil_unref(&kt->cg);
209 static void _kill_pid(struct cginfo *cg, const char *group, pid_t pid)
213 if (pid <= INIT_PID) /* block sending to all process or init */
216 r = cgutil_exist_group(cg, CTRL_MGR, group);
218 _E("send SIGKILL: exist: %s", strerror(errno));
222 _D("send SIGKILL: '%s' not exist", group);
226 /* TODO: check pid exist in group */
230 _D("send SIGKILL: pid %d not exist", pid);
234 r = kill(pid, SIGKILL);
236 _E("send SIGKILL: %s", strerror(errno));
239 static gboolean _ktimer_cb(gpointer data)
241 struct ktimer *kt = data;
243 _kill_pid(kt->cg, kt->group, kt->pid);
244 _kill_list = g_list_remove(_kill_list, kt);
250 static void _add_list(struct cginfo *cg, const char *group, pid_t pid)
254 kt = calloc(1, sizeof(*kt));
259 kt->group = strdup(group);
265 kt->cg = cgutil_ref(cg);
266 kt->tid = g_timeout_add_seconds(TERM_WAIT_SEC, _ktimer_cb, kt);
268 _kill_list = g_list_append(_kill_list, kt);
271 static inline void _del_list(GList *l)
280 g_source_remove(kt->tid);
282 _kill_list = g_list_delete_link(_kill_list, l);
285 static int _kill_pid_cb(void *user_data, const char *group, pid_t pid)
289 if (pid <= INIT_PID) /* block sending to all process or init */
292 r = kill(pid, SIGTERM);
294 _E("send SIGTERM: %s", strerror(errno));
296 _add_list(user_data, group, pid);
301 int service_stop(struct cginfo *cg, const char *group)
303 if (!cg || !group || !*group) {
308 return cgutil_group_foreach_pid(cg, CTRL_MGR, FILENAME(group),
312 void service_release(const char *group)
317 if (!group || !*group)
320 group = FILENAME(group);
323 for (l = _kill_list; l; l = g_list_next(l)) {
324 struct ktimer *k = l->data;
328 if (k->group && !strcmp(k->group, group))
335 int _send_to_sigkill(int pid)
343 if (killpg(pgid, SIGKILL) < 0)
348 int _resume_app(int pid)
353 __app_send_raw(pid, APP_RESUME_BY_PID, (unsigned char *)&dummy,
356 _E("resume packet timeout error");
358 _E("raise failed - %d resume fail\n", pid);
359 _E("we will term the app - %d\n", pid);
360 _send_to_sigkill(pid);
368 int _term_app(int pid)
372 (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
373 _D("terminate packet send error - use SIGKILL");
374 if (_send_to_sigkill(pid) < 0) {
375 _E("fail to killing - %d\n", pid);
383 int _fake_launch_app(int cmd, int pid, bundle * kb)
389 bundle_encode(kb, &kb_data, &datalen);
390 if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
391 _E("error request fake launch - error code = %d", ret);
396 static int __nofork_processing(int cmd, int pid, bundle * kb)
402 _D("resume app's pid : %d\n", pid);
403 if ((ret = _resume_app(pid)) < 0)
404 _E("__resume_app failed. error code = %d", ret);
405 _D("resume app done");
410 _D("fake launch pid : %d\n", pid);
411 if ((ret = _fake_launch_app(cmd, pid, kb)) < 0)
412 _E("fake_launch failed. error code = %d", ret);
413 _D("fake launch done");
419 static void __real_send(int clifd, int ret)
421 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
422 if (errno == EPIPE) {
423 _E("send failed due to EPIPE.\n");
425 _E("send fail to client");
431 int __sat_ui_is_running()
433 char *apppath = "/usr/apps/org.tizen.sat-ui/bin/sat-ui";
436 ret = __proc_iter_cmdline(NULL, apppath);
441 int __sat_ui_launch(char* appid, bundle* kb, int cmd, int caller_pid, int fd)
444 char *app_path = "/usr/apps/org.tizen.sat-ui/bin/sat-ui KEY_EXEC_TYPE 0";
446 char tmp_pid[MAX_PID_STR_BUFSZ];
448 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", caller_pid);
449 bundle_add(kb, AUL_K_CALLER_PID, tmp_pid);
451 pid = __sat_ui_is_running();
454 if (caller_pid == pid) {
455 _D("caller process & callee process is same.[%s:%d]", appid, pid);
456 pid = -ELOCALLAUNCH_ID;
457 } else if ((ret = __nofork_processing(cmd, pid, kb)) < 0) {
460 } else if (cmd != APP_RESUME) {
461 bundle_add(kb, AUL_K_HWACC, "NOT_USE");
462 bundle_add(kb, AUL_K_EXEC, app_path);
463 bundle_add(kb, AUL_K_PACKAGETYPE, "rpm");
464 pid = app_send_cmd(LAUNCHPAD_PID, cmd, kb);
467 __real_send(fd, pid);
470 //_status_add_app_info_list(appid, app_path, pid);
471 ac_server_check_launch_privilege(appid, "rpm", pid);
477 int _start_app(char* appid, bundle* kb, int cmd, int caller_pid, int fd)
481 char *componet = NULL;
482 char *multiple = NULL;
483 char *app_path = NULL;
484 char *pkg_type = NULL;
486 char tmp_pid[MAX_PID_STR_BUFSZ];
490 app2ext_handle *app2_handle = NULL;
492 if(strncmp(appid, "org.tizen.sat-ui", 18) == 0) {
493 pid = __sat_ui_launch(appid, kb, cmd, caller_pid, fd);
497 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", caller_pid);
498 bundle_add(kb, AUL_K_CALLER_PID, tmp_pid);
500 if (cmd == APP_START_RES)
501 bundle_add(kb, AUL_K_WAIT_RESULT, "1");
503 ai = appinfo_find(_laf, appid);
505 componet = appinfo_get_value(ai, AIT_COMP);
506 app_path = appinfo_get_value(ai, AIT_EXEC);
507 pkg_type = appinfo_get_value(ai, AIT_TYPE);
508 if (componet && strncmp(componet, "ui", 2) == 0) {
509 multiple = appinfo_get_value(ai, AIT_MULTI);
510 if (!multiple || strncmp(multiple, "false", 5) == 0) {
511 pid = _status_app_is_running_v2(appid);
515 if (caller_pid == pid) {
516 _D("caller process & callee process is same.[%s:%d]", appid, pid);
517 pid = -ELOCALLAUNCH_ID;
518 } else if ((ret = __nofork_processing(cmd, pid, kb)) < 0) {
521 } else if (cmd != APP_RESUME) {
522 hwacc = appinfo_get_value(ai, AIT_HWACC);
523 bundle_add(kb, AUL_K_HWACC, hwacc);
524 bundle_add(kb, AUL_K_EXEC, app_path);
525 bundle_add(kb, AUL_K_PACKAGETYPE, pkg_type);
526 if(strncmp(pkg_type, "wgt", 3) == 0) {
527 pid = app_send_cmd(WEB_LAUNCHPAD_PID, cmd, kb);
529 pid = app_send_cmd(LAUNCHPAD_PID, cmd, kb);
531 //_add_cgroup(_lcg, appid, pid);
533 } else if (componet && strncmp(componet, "svc", 3) == 0) {
534 pid = _status_app_is_running_v2(appid);
536 if ((ret = __nofork_processing(cmd, pid, kb)) < 0) {
539 } else if (cmd != APP_RESUME) {
540 pid = service_start(_lcg, appid, app_path, kb);
543 _E("unkown application");
546 location = app2ext_get_app_location(appid);
547 if (location == APP2EXT_SD_CARD)
549 app2_handle = app2ext_init(APP2EXT_SD_CARD);
550 if (app2_handle == NULL) {
551 _E("app2_handle : app2ext init failed\n");
555 ret = app2_handle->interface.enable(appid);
557 _E("app2_handle : app enable API fail Reason %d", ret);
560 app2ext_deinit(app2_handle);
563 __real_send(fd, pid);
566 //_status_add_app_info_list(appid, app_path, pid);
567 ret = ac_server_check_launch_privilege(appid, appinfo_get_value(ai, AIT_TYPE), pid);
568 return ret != AC_R_ERROR ? pid : -1;
575 int _launch_init(struct amdmgr* amd)