From d8c7c3ea06f86612de61a73b599761437ba0ad82 Mon Sep 17 00:00:00 2001 From: Taejeong Lee Date: Thu, 6 Dec 2012 19:07:27 +0900 Subject: [PATCH] WRT Launchpad Daemon Feature * wrt_launchpad_daemon helps wrt-client to launch more fast. * wrt_launchpad_daemon will load so files related wrt-client in advanced. [Issue#] N/A [Problem] WRT Launchpad Daemon Feature [Cause] N/A [Solution] N/A Change-Id: I8ba76ab3e84a978beae787fc5a37400313d3b525 --- packaging/wrt.spec | 61 ++ packaging/wrt_launchpad_daemon@.service | 12 + src/CMakeLists.txt | 1 + src/wrt-client/CMakeLists.txt | 1 + src/wrt-launchpad-daemon/CMakeLists.txt | 64 ++ src/wrt-launchpad-daemon/feature/preexec.h | 182 +++++ src/wrt-launchpad-daemon/include/app_signal.h | 35 + src/wrt-launchpad-daemon/include/app_sock.h | 72 ++ src/wrt-launchpad-daemon/include/aul_util.h | 59 ++ src/wrt-launchpad-daemon/include/menu_db_util.h | 226 ++++++ src/wrt-launchpad-daemon/include/perf.h | 68 ++ src/wrt-launchpad-daemon/include/simple_util.h | 89 +++ .../launchpad_src/access_control.h | 42 + src/wrt-launchpad-daemon/launchpad_src/config.h | 30 + src/wrt-launchpad-daemon/launchpad_src/gl.h | 32 + src/wrt-launchpad-daemon/launchpad_src/launchpad.c | 882 +++++++++++++++++++++ src/wrt-launchpad-daemon/launchpad_src/sigchild.h | 258 ++++++ src/wrt-launchpad-daemon/launchpad_src/util_x.c | 203 +++++ src/wrt-launchpad-daemon/launchpad_src/util_x.h | 32 + src/wrt-launchpad-daemon/legacy/preload.h | 171 ++++ .../legacy/preload_list_wrt.txt | 2 + src/wrt-launchpad-daemon/src/app_sock.c | 406 ++++++++++ src/wrt-launchpad-daemon/src/simple_util.c | 210 +++++ src/wrt-launchpad-daemon/wrt_launchpad_run.sh | 3 + wrt-engine.map | 1 + 25 files changed, 3142 insertions(+) create mode 100644 packaging/wrt_launchpad_daemon@.service mode change 100755 => 100644 src/CMakeLists.txt create mode 100644 src/wrt-launchpad-daemon/CMakeLists.txt create mode 100644 src/wrt-launchpad-daemon/feature/preexec.h create mode 100644 src/wrt-launchpad-daemon/include/app_signal.h create mode 100644 src/wrt-launchpad-daemon/include/app_sock.h create mode 100644 src/wrt-launchpad-daemon/include/aul_util.h create mode 100644 src/wrt-launchpad-daemon/include/menu_db_util.h create mode 100644 src/wrt-launchpad-daemon/include/perf.h create mode 100644 src/wrt-launchpad-daemon/include/simple_util.h create mode 100644 src/wrt-launchpad-daemon/launchpad_src/access_control.h create mode 100644 src/wrt-launchpad-daemon/launchpad_src/config.h create mode 100644 src/wrt-launchpad-daemon/launchpad_src/gl.h create mode 100644 src/wrt-launchpad-daemon/launchpad_src/launchpad.c create mode 100644 src/wrt-launchpad-daemon/launchpad_src/sigchild.h create mode 100644 src/wrt-launchpad-daemon/launchpad_src/util_x.c create mode 100644 src/wrt-launchpad-daemon/launchpad_src/util_x.h create mode 100644 src/wrt-launchpad-daemon/legacy/preload.h create mode 100644 src/wrt-launchpad-daemon/legacy/preload_list_wrt.txt create mode 100644 src/wrt-launchpad-daemon/src/app_sock.c create mode 100644 src/wrt-launchpad-daemon/src/simple_util.c create mode 100644 src/wrt-launchpad-daemon/wrt_launchpad_run.sh diff --git a/packaging/wrt.spec b/packaging/wrt.spec index 2a32abc..ca37801 100644 --- a/packaging/wrt.spec +++ b/packaging/wrt.spec @@ -7,6 +7,10 @@ Group: Development/Libraries License: Apache License, Version 2.0 URL: N/A Source0: %{name}-%{version}.tar.gz +## wrt-launchpad-daemon ####################################################### +#Source101: wrt_launchpad_daemon@.service +############################################################################### + BuildRequires: cmake BuildRequires: gettext BuildRequires: edje-tools @@ -42,6 +46,17 @@ BuildRequires: pkgconfig(wrt-plugin-js-overlay) BuildRequires: pkgconfig(dpl-encryption) BuildRequires: pkgconfig(wrt-popup-runner) +## wrt-launchpad-daemon ####################################################### +BuildRequires: pkgconfig(app-checker) +BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(dbus-glib-1) +BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(x11) +BuildRequires: pkgconfig(aul) +############################################################################### + %description web runtime @@ -70,6 +85,26 @@ mkdir -p %{buildroot}/usr/share/license cp LICENSE %{buildroot}/usr/share/license/%{name} %make_install +## wrt-launchpad-daemon ####################################################### +mkdir -p %{buildroot}/etc/init.d +install -m 755 src/wrt-launchpad-daemon/wrt_launchpad_run.sh %{buildroot}/%{_sysconfdir}/init.d + +mkdir -p %{buildroot}/etc/rc.d/rc3.d +mkdir -p %{buildroot}/etc/rc.d/rc4.d +ln -sf ../../init.d/wrt_launchpad_run.sh %{buildroot}/%{_sysconfdir}/rc.d/rc3.d/S15wrt_launchpad_run +ln -sf ../../init.d/wrt_launchpad_run.sh %{buildroot}/%{_sysconfdir}/rc.d/rc4.d/S80wrt_launchpad_run + +#systemd +#mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants +#install -m 0644 %SOURCE101 %{buildroot}%{_libdir}/systemd/system/wrt_launchpad_daemon@.service +#ln -s ../launchpad-preload@.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/wrt_launchpad_daemon@app.service +# +#%preun +#if [ $1 == 0 ]; then +# systemctl stop wrt_launchpad_daemon@app.service +#fi +############################################################################### + %clean rm -rf %{buildroot} @@ -83,8 +118,23 @@ rm -rf %{buildroot} chmod +s /usr/bin/wrt-launcher +## wrt-launchpad-daemon ####################################################### +#systemd +#/sbin/ldconfig +#systemctl daemon-reload +#if [ $1 == 1 ]; then +# systemctl restart wrt_launchpad_daemon@app.service +#fi +############################################################################### + echo "[WRT] wrt postinst done ..." +## wrt-launchpad-daemon ####################################################### +#systemd +#%postun -p /sbin/ldconfig +#systemctl daemon-reload +############################################################################### + %files %manifest wrt.manifest %{_libdir}/*.so @@ -102,6 +152,17 @@ echo "[WRT] wrt postinst done ..." %attr(644,root,root) %{_datadir}/edje/ace/* %attr(644,root,root) /usr/etc/wrt/* +## wrt-launchpad-daemon ####################################################### +%attr(755,root,root) %{_bindir}/wrt_launchpad_daemon +/usr/share/aul/preload_list_wrt.txt +%{_sysconfdir}/init.d/wrt_launchpad_run.sh +%attr(0755,root,root) %{_sysconfdir}/rc.d/rc3.d/S15wrt_launchpad_run +%attr(0755,root,root) %{_sysconfdir}/rc.d/rc4.d/S80wrt_launchpad_run +#systemd +#%{_libdir}/systemd/system/graphical.target.wants/wrt_launchpad_daemon@app.service +#%{_libdir}/systemd/system/wrt_launchpad_daemon@.service +############################################################################### + %files devel %{_includedir}/* %{_libdir}/pkgconfig/* diff --git a/packaging/wrt_launchpad_daemon@.service b/packaging/wrt_launchpad_daemon@.service new file mode 100644 index 0000000..4613db6 --- /dev/null +++ b/packaging/wrt_launchpad_daemon@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Start the wrt_launchpad_daemon + +[Service] +EnvironmentFile=/etc/sysconfig/tizen-mobile-ui +Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%I/dbus/user_bus_socket +Environment=DISPLAY=:0 +Environment=XDG_RUNTIME_DIR=/run/user/%I +ExecStart=/usr/bin/wrt_launchpad_daemon + +[Install] +WantedBy=graphical.target diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt old mode 100755 new mode 100644 index e81c8ab..370b320 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -159,3 +159,4 @@ ADD_SUBDIRECTORY(plugin-service) IF(PROFILING) ADD_SUBDIRECTORY(profiling) ENDIF(PROFILING) +ADD_SUBDIRECTORY(wrt-launchpad-daemon) diff --git a/src/wrt-client/CMakeLists.txt b/src/wrt-client/CMakeLists.txt index 96426d2..ae644ee 100644 --- a/src/wrt-client/CMakeLists.txt +++ b/src/wrt-client/CMakeLists.txt @@ -40,6 +40,7 @@ ADD_EXECUTABLE(${TARGET_WRT_CLIENT} TARGET_LINK_LIBRARIES(${TARGET_WRT_CLIENT} ${CLIENT_DEP_LIBRARIES} ${TARGET_CORE_MODULE_LIB} + "-pie" ) SET_TARGET_PROPERTIES(${TARGET_WRT_CLIENT} PROPERTIES diff --git a/src/wrt-launchpad-daemon/CMakeLists.txt b/src/wrt-launchpad-daemon/CMakeLists.txt new file mode 100644 index 0000000..33aa5b6 --- /dev/null +++ b/src/wrt-launchpad-daemon/CMakeLists.txt @@ -0,0 +1,64 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# @file CMakeLists.txt +# @author Tae-Jeong Lee (taejeong.lee@samsung.com) +# @version 0.1 +# + +SET(WRT_LAUNCH_PAD_NAME "wrt_launchpad_daemon") + +ADD_DEFINITIONS("-DSHARE_PREFIX=\"/usr/share/aul\"") + +PKG_CHECK_MODULES(WRT_LAUNCH_PAD_DEPS + aul + dlog + app-checker + bundle + dbus-glib-1 + glib-2.0 + libsmack + libprivilege-control + x11 + sqlite3 + REQUIRED +) + +SET(WRT_LAUNCH_PAD_INCLUDE_DIRS + ${PROJECT_SOURCE_DIR}/src/wrt-launchpad-daemon/include + ${PROJECT_SOURCE_DIR}/src/wrt-launchpad-daemon/legacy + ${PROJECT_SOURCE_DIR}/src/wrt-launchpad-daemon/feature + ${WRT_LAUNCH_PAD_DEPS_INCLUDE_DIRS} +) + +INCLUDE_DIRECTORIES(${WRT_LAUNCH_PAD_INCLUDE_DIRS}) + +#build executable +ADD_EXECUTABLE( ${WRT_LAUNCH_PAD_NAME} + src/app_sock.c + src/simple_util.c + launchpad_src/launchpad.c + launchpad_src/util_x.c +) + +#link libraries +TARGET_LINK_LIBRARIES( ${WRT_LAUNCH_PAD_NAME} + ${WRT_LAUNCH_PAD_DEPS_LIBRARIES} + ${CMAKE_DL_LIBS} +) + +#install +INSTALL(TARGETS ${WRT_LAUNCH_PAD_NAME} DESTINATION bin) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/legacy/preload_list_wrt.txt DESTINATION /usr/share/aul ) diff --git a/src/wrt-launchpad-daemon/feature/preexec.h b/src/wrt-launchpad-daemon/feature/preexec.h new file mode 100644 index 0000000..863d330 --- /dev/null +++ b/src/wrt-launchpad-daemon/feature/preexec.h @@ -0,0 +1,182 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifdef PREEXEC_ACTIVATE + +#include +#include +#define PREEXEC_FILE SHARE_PREFIX"/preexec_list.txt" + +static int preexec_initialized = 0; + +GSList *preexec_list = NULL; + +typedef struct _preexec_list_t { + char *pkg_type; + char *so_path; + int (*dl_do_pre_exe) (char *, char *); +} preexec_list_t; + +static void __preexec_list_free() +{ + GSList *iter = NULL; + preexec_list_t *type_t; + + for (iter = preexec_list; iter != NULL; iter = g_slist_next(iter)) { + type_t = iter->data; + if (type_t) { + if (type_t->pkg_type) + free(type_t->pkg_type); + if (type_t->so_path) + free(type_t->so_path); + free(type_t); + } + } + g_slist_free(preexec_list); + return; +} + +static inline void __preexec_init(int argc, char **argv) +{ + void *handle = NULL; + FILE *preexec_file; + char *saveptr = NULL; + char line[MAX_LOCAL_BUFSZ]; + char *type = NULL; + char *sopath = NULL; + char *symbol = NULL; + int (*func) (char *, char *) = NULL; + preexec_list_t *type_t = NULL; + + // warning: unused parameter + argc = argc; + argv = argv; + + preexec_file = fopen(PREEXEC_FILE, "rt"); + if (preexec_file == NULL) { + _E("no preexec\n"); + return; + } + + _D("preexec start\n"); + + while (fgets(line, MAX_LOCAL_BUFSZ, preexec_file) > (char*)0) { + /* Parse each line */ + if (line[0] == '#' || line[0] == '\0') + continue; + + type = strtok_r(line, ":\f\n\r\t\v ", &saveptr); + if (type == NULL) + continue; + sopath = strtok_r(NULL, ",\f\n\r\t\v ", &saveptr); + if (sopath == NULL) + continue; + symbol = strtok_r(NULL, ",\f\n\r\t\v ", &saveptr); + if (symbol == NULL) + continue; + + type_t = (preexec_list_t *) calloc(1, sizeof(preexec_list_t)); + if (type_t == NULL) { + _E("no available memory\n"); + __preexec_list_free(); + return; + } + + handle = dlopen(sopath, RTLD_NOW); + if (handle == NULL) { + free(type_t); + continue; + } + _D("preexec %s %s# - handle : %x\n", type, sopath, handle); + + func = dlsym(handle, symbol); + if (func == NULL) { + _E("failed to get symbol type:%s path:%s\n", + type, sopath); + free(type_t); + dlclose(handle); + continue; + } + + type_t->pkg_type = strdup(type); + if (type_t->pkg_type == NULL) { + _E("no available memory\n"); + free(type_t); + __preexec_list_free(); + return; + } + type_t->so_path = strdup(sopath); + if (type_t->so_path == NULL) { + _E("no available memory\n"); + free(type_t->pkg_type); + free(type_t); + __preexec_list_free(); + return; + } + type_t->dl_do_pre_exe = func; + + preexec_list = g_slist_append(preexec_list, (void *)type_t); + } + + fclose(preexec_file); + preexec_initialized = 1; +} + +static inline void __preexec_run(const char *pkg_type, const char *pkg_name, + const char *app_path) +{ + GSList *iter = NULL; + preexec_list_t *type_t; + + if (!preexec_initialized) + return; + + for (iter = preexec_list; iter != NULL; iter = g_slist_next(iter)) { + type_t = iter->data; + if (type_t) { + if (!strcmp(pkg_type, type_t->pkg_type)) { + if (type_t->dl_do_pre_exe != NULL) { + type_t->dl_do_pre_exe((char *)pkg_name, + (char *)app_path); + _D("called dl_do_pre_exe() type: %s", + pkg_type); + } else { + _E("no symbol for this type: %s", + pkg_type); + } + } + } + } + +} + +#else + +static inline void __preexec_init(int argc, char **argv) +{ +} + +static inline void __preexec_run(const char *pkg_type, const char *pkg_name, + const char *app_path) +{ +} + +#endif diff --git a/src/wrt-launchpad-daemon/include/app_signal.h b/src/wrt-launchpad-daemon/include/app_signal.h new file mode 100644 index 0000000..29d2e83 --- /dev/null +++ b/src/wrt-launchpad-daemon/include/app_signal.h @@ -0,0 +1,35 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef __APP_DBUS_H__ +#define __APP_DBUS_H__ + +#include +#include +#include + +#define AUL_DBUS_PATH "/aul/dbus_handler" +#define AUL_DBUS_SIGNAL_INTERFACE "com.samsung.aul.signal" +#define AUL_DBUS_APPDEAD_SIGNAL "app_dead" +#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch" + +#endif diff --git a/src/wrt-launchpad-daemon/include/app_sock.h b/src/wrt-launchpad-daemon/include/app_sock.h new file mode 100644 index 0000000..1361ed6 --- /dev/null +++ b/src/wrt-launchpad-daemon/include/app_sock.h @@ -0,0 +1,72 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef __APP_PKT_H_ +#define __APP_PKT_H_ + +#include +#define __USE_GNU +#include +#include + +enum app_cmd { + APP_START, + APP_OPEN, + APP_RESUME, + APP_RESUME_BY_PID, + APP_TERM_BY_PID, + APP_RESULT, + APP_START_RES, + APP_CANCEL, + APP_KILL_BY_PID, + APP_ADD_HISTORY, + APP_RUNNING_INFO, + APP_RUNNING_INFO_RESULT, + APP_IS_RUNNING, + APP_KEY_EVENT, + APP_KEY_RESERVE, + APP_KEY_RELEASE, + APP_STATUS_UPDATE, + APP_RELEASED, + APP_RUNNING_LIST_UPDATE +}; + +#define AUL_SOCK_PREFIX "/tmp/alaunch" +#define AUL_SOCK_MAXBUFF 65535 +#define LAUNCHPAD_PID -1 +#define WRT_LAUNCHPAD_PID -3 +#define ELOCALLAUNCH_ID 128 + +typedef struct _app_pkt_t { + int cmd; + int len; + unsigned char data[1]; +} app_pkt_t; + +int __create_server_sock(int pid); +int __create_client_sock(int pid); +int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen); +app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr); +app_pkt_t *__app_send_cmd_with_result(int pid, int cmd); + +#endif + diff --git a/src/wrt-launchpad-daemon/include/aul_util.h b/src/wrt-launchpad-daemon/include/aul_util.h new file mode 100644 index 0000000..d86a3f9 --- /dev/null +++ b/src/wrt-launchpad-daemon/include/aul_util.h @@ -0,0 +1,59 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef __AUL_UTIL_H_ +#define __AUL_UTIL_H_ + +#define AUL_UTIL_PID -2 + +#define MAX_PACKAGE_STR_SIZE 512 +#define MAX_PACKAGE_APP_PATH_SIZE 512 +#define MAX_RUNNING_APP_INFO 512 + +struct history_data { + char pkg_name[MAX_PACKAGE_STR_SIZE]; + char app_path[MAX_PACKAGE_APP_PATH_SIZE]; + int pid; + int len; + unsigned char data[1]; +}; + +typedef struct _app_status_info_t{ + char appid[MAX_PACKAGE_STR_SIZE]; + char app_path[MAX_PACKAGE_APP_PATH_SIZE]; + int status; + int pid; +} app_status_info_t; + +struct amdmgr { + struct appinfomgr *af; /* appinfo manager */ + struct cginfo *cg; /* cgroup infomation */ +}; + +int _add_app_status_info_list(char *appid, int pid); +int _update_app_status_info_list(int pid, int status); +int _remove_app_status_info_list(int pid); + +#endif + + + diff --git a/src/wrt-launchpad-daemon/include/menu_db_util.h b/src/wrt-launchpad-daemon/include/menu_db_util.h new file mode 100644 index 0000000..ab25548 --- /dev/null +++ b/src/wrt-launchpad-daemon/include/menu_db_util.h @@ -0,0 +1,226 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#include +#include +#include "simple_util.h" + +#define MAX_PATH_LEN 1024 + +#define AUL_APP_INFO_FLD_PKG_NAME "package" +#define AUL_APP_INFO_FLD_APP_PATH "exec" +#define AUL_APP_INFO_FLD_APP_TYPE "x_slp_packagetype" +#define AUL_APP_INFO_FLD_WIDTH "x_slp_baselayoutwidth" +#define AUL_APP_INFO_FLD_HEIGHT "x_slp_baselayoutheight" +#define AUL_APP_INFO_FLD_VERTICAL "x_slp_ishorizontalscale" +#define AUL_APP_INFO_FLD_MULTIPLE "x_slp_multiple" +#define AUL_APP_INFO_FLD_TASK_MANAGE "x_slp_taskmanage" +#define AUL_APP_INFO_FLD_MIMETYPE "mimetype" +#define AUL_APP_INFO_FLD_SERVICE "x_slp_service" + +#define AUL_RETRIEVE_PKG_NAME "package = '?'" +#define AUL_RETRIEVE_APP_PATH "exec = '?'" +#define AUL_RETRIEVE_MIMETYPE "mimetype like '?'" +#define AUL_RETRIEVE_SERVICE "x_slp_service like '?'" + +typedef struct { + char *pkg_name; /* package */ + char *app_path; /* exec */ + char *original_app_path; /* exec */ + char *pkg_type; /* x_slp_packagetype */ +} app_info_from_db; + +static inline char *_get_pkgname(app_info_from_db *menu_info) +{ + if (menu_info->pkg_name == NULL) + return NULL; + return menu_info->pkg_name; +} + +static inline char *_get_app_path(app_info_from_db *menu_info) +{ + int i = 0; + int path_len = -1; + + if (menu_info->app_path == NULL) + return NULL; + + while (menu_info->app_path[i] != 0) { + if (menu_info->app_path[i] == ' ' + || menu_info->app_path[i] == '\t') { + path_len = i; + break; + } + i++; + } + + if (path_len == 0) { + free(menu_info->app_path); + menu_info->app_path = NULL; + } else if (path_len > 0) { + char *tmp_app_path = malloc(sizeof(char) * (path_len + 1)); + if(tmp_app_path == NULL) + return NULL; + snprintf(tmp_app_path, path_len + 1, "%s", menu_info->app_path); + free(menu_info->app_path); + menu_info->app_path = tmp_app_path; + } + + return menu_info->app_path; +} + +static inline char *_get_original_app_path(app_info_from_db *menu_info) +{ + if (menu_info->original_app_path == NULL) + return NULL; + return menu_info->original_app_path; +} + +static inline void _free_app_info_from_db(app_info_from_db *menu_info) +{ + if (menu_info != NULL) { + if (menu_info->pkg_name != NULL) + free(menu_info->pkg_name); + if (menu_info->app_path != NULL) + free(menu_info->app_path); + if (menu_info->original_app_path != NULL) + free(menu_info->original_app_path); + free(menu_info); + } +} + +static inline app_info_from_db *_get_app_info_from_db_by_pkgname( + const char *pkgname) +{ + app_info_from_db *menu_info; + ail_appinfo_h handle; + ail_error_e ret; + char *str = NULL; + + menu_info = calloc(1, sizeof(app_info_from_db)); + if (menu_info == NULL) { + return NULL; + } + + ret = ail_get_appinfo(pkgname, &handle); + if (ret != AIL_ERROR_OK) { + _free_app_info_from_db(menu_info); + return NULL; + } + + ret = ail_appinfo_get_str(handle, AIL_PROP_PACKAGE_STR, &str); + if (str) { + menu_info->pkg_name = strdup(str); + str = NULL; + } + + ret = ail_appinfo_get_str(handle, AIL_PROP_EXEC_STR, &str); + if (str) { + menu_info->app_path = strdup(str); + str = NULL; + } + + if (menu_info->app_path != NULL) + menu_info->original_app_path = strdup(menu_info->app_path); + + ret = ail_appinfo_get_str(handle, AIL_PROP_X_SLP_PACKAGETYPE_STR, &str); + if (str) { + menu_info->pkg_type = strdup(str); + str = NULL; + } + + ret = ail_destroy_appinfo(handle); + if (ret != AIL_ERROR_OK) { + _E("ail_destroy_appinfo failed"); + } + + if (!_get_app_path(menu_info)) { + _free_app_info_from_db(menu_info); + return NULL; + } + + return menu_info; +} + +static inline ail_cb_ret_e __appinfo_func(const ail_appinfo_h appinfo, void *user_data) +{ + app_info_from_db *menu_info = (app_info_from_db *)user_data; + char *package; + + ail_appinfo_get_str(appinfo, AIL_PROP_PACKAGE_STR, &package); + + menu_info->pkg_name = strdup(package); + + return AIL_CB_RET_CANCEL; /*return AIL_CB_RET_CONTINUE;*/ +} + +static inline app_info_from_db *_get_app_info_from_db_by_apppath( + const char *apppath) +{ + app_info_from_db *menu_info = NULL; + ail_filter_h filter; + ail_error_e ret; + int count; + + if (apppath == NULL) + return NULL; + + menu_info = calloc(1, sizeof(app_info_from_db)); + if (menu_info == NULL) + return NULL; + + ret = ail_filter_new(&filter); + if (ret != AIL_ERROR_OK) { + _free_app_info_from_db(menu_info); + return NULL; + } + + ret = ail_filter_add_str(filter, AIL_PROP_X_SLP_EXE_PATH, apppath); + if (ret != AIL_ERROR_OK) { + ail_filter_destroy(filter); + _free_app_info_from_db(menu_info); + return NULL; + } + + ret = ail_filter_count_appinfo(filter, &count); + if (ret != AIL_ERROR_OK) { + ail_filter_destroy(filter); + _free_app_info_from_db(menu_info); + return NULL; + } + if (count < 1) { + ail_filter_destroy(filter); + _free_app_info_from_db(menu_info); + return NULL; + } + + ail_filter_list_appinfo_foreach(filter, __appinfo_func, (void *)menu_info); + + ail_filter_destroy(filter); + + menu_info->app_path = strdup(apppath); + menu_info->original_app_path = strdup(apppath); + + return menu_info; + +} + diff --git a/src/wrt-launchpad-daemon/include/perf.h b/src/wrt-launchpad-daemon/include/perf.h new file mode 100644 index 0000000..fb2582f --- /dev/null +++ b/src/wrt-launchpad-daemon/include/perf.h @@ -0,0 +1,68 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef __PERF_H__ +#define __PERF_H__ + +#ifdef PERF_ACTIVATE + +#include +static struct timeval __g_base_time = { + .tv_sec = 0, + .tv_usec = 0 +}; + +#define INIT_PERF(kb)\ +do {\ + const char *tmp;\ + struct timeval tv;\ + tmp = bundle_get_val(kb, AUL_K_STARTTIME);\ + if (tmp != NULL)\ + sscanf(tmp, "%ld/%ld", &tv.tv_sec, &tv.tv_usec);\ + else\ + gettimeofday(&tv, NULL);\ + __g_base_time.tv_sec = tv.tv_sec;\ + __g_base_time.tv_usec = tv.tv_usec;\ +} while (0); + +#define PERF(fmt, arg...)\ +do {\ + struct timeval cur;\ + struct timeval res;\ + gettimeofday(&cur, NULL);\ + if (__g_base_time.tv_sec != 0) {\ + timersub(&cur, &__g_base_time, &res);\ + printf("%c[1;31m[%s,%d] %ld sec %ld msec "fmt" %c[0m\n",\ + 27, __FUNCTION__, __LINE__, \ + res.tv_sec, res.tv_usec/1000, ##arg, 27);\ + } \ +} while (0); + +#else + +#define INIT_PERF(kb) +#define PERF(fmt, arg...) + +#endif + +#endif + diff --git a/src/wrt-launchpad-daemon/include/simple_util.h b/src/wrt-launchpad-daemon/include/simple_util.h new file mode 100644 index 0000000..2079b20 --- /dev/null +++ b/src/wrt-launchpad-daemon/include/simple_util.h @@ -0,0 +1,89 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef __SIMPLE_UTIL__ +#define __SIMPLE_UTIL__ + +#include +#include +#include + +#ifdef LAUNCHPAD_LOG +#undef LOG_TAG +#define LOG_TAG "AULD" +#else +#undef LOG_TAG +#define LOG_TAG "AUL" +#endif +#ifdef AMD_LOG +#undef LOG_TAG +#define LOG_TAG "AMD" +#endif + + +#define MAX_LOCAL_BUFSZ 128 +#define MAX_PID_STR_BUFSZ 20 + +#define _E(fmt, arg...) LOGE("[%s,%d] "fmt, __FUNCTION__, __LINE__, ##arg) +#define _D(fmt, arg...) LOGD("[%s,%d] "fmt, __FUNCTION__, __LINE__, ##arg) + +#define retvm_if(expr, val, fmt, arg...) do { \ + if (expr) { \ + _E(fmt, ##arg); \ + _E("(%s) -> %s() return", #expr, __FUNCTION__); \ + return (val); \ + } \ +} while (0) + +#define retv_if(expr, val) do { \ + if (expr) { \ + _E("(%s) -> %s() return", #expr, __FUNCTION__); \ + return (val); \ + } \ +} while (0) + +int __proc_iter_cmdline(int (*iterfunc) + (const char *dname, const char *cmdline, void *priv), + void *priv); +int __proc_iter_pgid(int pgid, int (*iterfunc) (int pid, void *priv), + void *priv); +char *__proc_get_cmdline_bypid(int pid); + +static inline const char *FILENAME(const char *filename) +{ + const char *p; + const char *r; + + if (!filename) + return NULL; + + r = p = filename; + while (*p) { + if (*p == '/') + r = p + 1; + p++; + } + + return r; +} + +#endif diff --git a/src/wrt-launchpad-daemon/launchpad_src/access_control.h b/src/wrt-launchpad-daemon/launchpad_src/access_control.h new file mode 100644 index 0000000..6ba035c --- /dev/null +++ b/src/wrt-launchpad-daemon/launchpad_src/access_control.h @@ -0,0 +1,42 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifdef DAC_ACTIVATE + +#include + +#define INHOUSE_UID 5000 +static inline int __set_access(const char* pkg_name, const char* pkg_type, const char* app_path) +{ + return set_app_privilege(pkg_name, pkg_type, app_path); +} + +#else + +static inline int __set_access(const char* pkg_name, const char* pkg_type, const char* app_path) +{ + return 0; +} + +#endif + + diff --git a/src/wrt-launchpad-daemon/launchpad_src/config.h b/src/wrt-launchpad-daemon/launchpad_src/config.h new file mode 100644 index 0000000..f5728cf --- /dev/null +++ b/src/wrt-launchpad-daemon/launchpad_src/config.h @@ -0,0 +1,30 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#define LAUNCHPAD_LOG +#define DAC_ACTIVATE +#define PRELOAD_ACTIVATE +#define PREEXEC_ACTIVATE +/*#define GL_ACTIVATE*/ +/*#define HEAPDGB_ACTIVATE*/ +/*#define PERF_ACTIVATE*/ + diff --git a/src/wrt-launchpad-daemon/launchpad_src/gl.h b/src/wrt-launchpad-daemon/launchpad_src/gl.h new file mode 100644 index 0000000..4add496 --- /dev/null +++ b/src/wrt-launchpad-daemon/launchpad_src/gl.h @@ -0,0 +1,32 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifdef GL_ACTIVATE + +#define USE_ENGINE(engine) setenv("ELM_ENGINE", engine, 1); + +#else + +#define USE_ENGINE(engine) + +#endif + diff --git a/src/wrt-launchpad-daemon/launchpad_src/launchpad.c b/src/wrt-launchpad-daemon/launchpad_src/launchpad.c new file mode 100644 index 0000000..b1b9a94 --- /dev/null +++ b/src/wrt-launchpad-daemon/launchpad_src/launchpad.c @@ -0,0 +1,882 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +/* + * simple AUL daemon - launchpad + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "app_sock.h" +#include + +#include "config.h" + +#include "menu_db_util.h" +#include "simple_util.h" +#include "access_control.h" +#include "preload.h" +#include "preexec.h" +#include "perf.h" +#include "sigchild.h" +#include "aul_util.h" + +#include "util_x.h" + +#include "gl.h" + +#include +#include + +#define _static_ static inline +#define POLLFD_MAX 1 +#define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */ +#define AUL_POLL_CNT 15 +#define AUL_PR_NAME 16 +#define PATH_APP_ROOT "/opt/usr/apps" +#define PATH_DATA "/data" +#define SDK_CODE_COVERAGE "CODE_COVERAGE" +#define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS" +#define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so" + + +static char *launchpad_cmdline; +static int initialized = 0; + + +_static_ void __set_oom(); +_static_ void __set_env(app_info_from_db * menu_info, bundle * kb); +_static_ int __prepare_exec(const char *pkg_name, + const char *app_path, app_info_from_db * menu_info, + bundle * kb); +_static_ int __fake_launch_app(int cmd, int pid, bundle * kb); +_static_ char **__create_argc_argv(bundle * kb, int *margc); +_static_ int __normal_fork_exec(int argc, char **argv); +_static_ void __real_launch(const char *app_path, bundle * kb); +_static_ void __add_history(int caller, int callee, const char *pkgname, + bundle *b, const char *app_path); +static inline int __parser(const char *arg, char *out, int out_size); +_static_ void __modify_bundle(bundle * kb, int caller_pid, + app_info_from_db * menu_info, int cmd); +_static_ int __child_raise_win_by_x(int pid, void *priv); +_static_ int __raise_win_by_x(int pid); +_static_ int __send_to_sigkill(int pid); +_static_ int __term_app(int pid); +_static_ int __resume_app(int pid); +_static_ void __real_send(int clifd, int ret); +_static_ void __send_result_to_caller(int clifd, int ret); +_static_ void __launchpad_main_loop(int main_fd); +_static_ int __launchpad_pre_init(int argc, char **argv); +_static_ int __launchpad_post_init(); + +extern ail_error_e ail_db_close(void); + + + +_static_ void __set_oom() +{ + char buf[MAX_LOCAL_BUFSZ]; + FILE *fp; + + /* we should reset oomadj value as default because child + inherits from parent oom_adj*/ + snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid()); + fp = fopen(buf, "w"); + if (fp == NULL) + return; + fprintf(fp, "%d", -16); + fclose(fp); +} + +_static_ void __set_sdk_env(app_info_from_db* menu_info, char* str) { + char buf[MAX_LOCAL_BUFSZ]; + int ret; + + _D("key : %s / value : %s", AUL_K_SDK, str); + /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/ + /* GCOV_PREFIX contains the prefix to add to the absolute paths in the object file. */ + /* Prefix can be absolute, or relative. The default is no prefix. */ + /* GCOV_PREFIX_STRIP indicates the how many initial directory names */ + /* to stripoff the hardwired absolute paths. Default value is 0. */ + if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) { + snprintf(buf, MAX_LOCAL_BUFSZ, PATH_APP_ROOT"/%s"PATH_DATA, _get_pkgname(menu_info)); + ret = setenv("GCOV_PREFIX", buf, 1); + _D("GCOV_PREFIX : %d", ret); + ret = setenv("GCOV_PREFIX_STRIP", "4096", 1); + _D("GCOV_PREFIX_STRIP : %d", ret); + } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) { + ret = setenv("LD_PRELOAD", PATH_DA_SO, 1); + _D("LD_PRELOAD : %d", ret); + } +} + + +_static_ void __set_env(app_info_from_db * menu_info, bundle * kb) +{ + const char *str; + const char **str_array; + int len; + int i; + + setenv("PKG_NAME", _get_pkgname(menu_info), 1); + + USE_ENGINE("gl") + + str = bundle_get_val(kb, AUL_K_STARTTIME); + if (str != NULL) + setenv("APP_START_TIME", str, 1); + + if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) { + str_array = bundle_get_str_array(kb, AUL_K_SDK, &len); + if(str_array != NULL) { + for (i = 0; i < len; i++) { + _D("index : [%d]", i); + __set_sdk_env(menu_info, (char *)str_array[i]); + } + } + } else { + str = bundle_get_val(kb, AUL_K_SDK); + if(str != NULL) { + __set_sdk_env(menu_info, (char *)str); + } + } +} + +_static_ int __prepare_exec(const char *pkg_name, + const char *app_path, app_info_from_db * menu_info, + bundle * kb) +{ + char *file_name; + char process_name[AUL_PR_NAME]; + + /* Set new session ID & new process group ID*/ + /* In linux, child can set new session ID without check permission */ + /* TODO : should be add to check permission in the kernel*/ + setsid(); + + __preexec_run(menu_info->pkg_type, pkg_name, app_path); + + /* SET OOM*/ + __set_oom(); + + /* SET PRIVILEGES*/ + if (__set_access(pkg_name, menu_info->pkg_type, app_path) < 0) { + _D("fail to set privileges - check your package's credential\n"); + return -1; + } + /* SET DUMPABLE - for coredump*/ + prctl(PR_SET_DUMPABLE, 1); + + /* SET PROCESS NAME*/ + if (app_path == NULL) { + _D("app_path should not be NULL - check menu db"); + return -1; + } + file_name = strrchr(app_path, '/') + 1; + if (file_name == NULL) { + _D("can't locate file name to execute"); + return -1; + } + memset(process_name, '\0', AUL_PR_NAME); + snprintf(process_name, AUL_PR_NAME, "%s", file_name); + prctl(PR_SET_NAME, process_name); + + /* SET ENVIROMENT*/ + __set_env(menu_info, kb); + + return 0; +} + +_static_ int __fake_launch_app(int cmd, int pid, bundle * kb) +{ + int datalen; + int ret; + bundle_raw *kb_data; + + bundle_encode(kb, &kb_data, &datalen); + if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0) + _E("error request fake launch - error code = %d", ret); + free(kb_data); + return ret; +} + +_static_ char **__create_argc_argv(bundle * kb, int *margc) +{ + char **argv; + int argc; + + argc = bundle_export_to_argv(kb, &argv); + + *margc = argc; + return argv; +} + +_static_ int __normal_fork_exec(int argc, char **argv) +{ + _D("start real fork and exec\n"); + + // warning: unused parameter + argc = argc; + + if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */ + if (errno == EACCES) + _E("such a file is no executable - %s", argv[0]); + else + _E("unknown executable error - %s", argv[0]); + return -1; + } + /* never reach*/ + return 0; +} + +_static_ void __real_launch(const char *app_path, bundle * kb) +{ + int app_argc; + char **app_argv; + int i; + + app_argv = __create_argc_argv(kb, &app_argc); + app_argv[0] = strdup(app_path); + + for (i = 0; i < app_argc; i++) + _D("input argument %d : %s##", i, app_argv[i]); + + PERF("setup argument done"); + _E("lock up test log(no error) : setup argument done"); + + /* Temporary log: launch time checking */ + LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path); + + __preload_exec(app_argc, app_argv); + + __normal_fork_exec(app_argc, app_argv); +} + +_static_ void __add_history(int caller, int callee, const char *pkgname, + bundle *b, const char *app_path) +{ + struct history_data *hd; + bundle_raw *kb_data; + int len; + + _D("***** HISTORY *****\n"); + _D("%d ==> %d(%s) \n", caller, callee, pkgname); + _D("*******************\n"); + + if (b) { + bundle_encode(b, (bundle_raw **)&kb_data, &len); + hd = (struct history_data *)malloc(sizeof(char) * (len+1033)); + + strncpy(hd->pkg_name, pkgname, MAX_PACKAGE_STR_SIZE-1); + strncpy(hd->app_path, app_path, MAX_PACKAGE_APP_PATH_SIZE-1); + hd->pid = callee; + hd->len = len; + memcpy(hd->data, kb_data, len); + + __app_send_raw(AUL_UTIL_PID, APP_ADD_HISTORY, (unsigned char *)hd, + hd->len+1033); + free(kb_data); + free(hd); + } else { + hd = (struct history_data *)malloc(sizeof(char) * 1033); + + strncpy(hd->pkg_name, pkgname, MAX_PACKAGE_STR_SIZE-1); + strncpy(hd->app_path, app_path, MAX_PACKAGE_APP_PATH_SIZE-1); + hd->pid = callee; + hd->len = 0; + + __app_send_raw(AUL_UTIL_PID, APP_ADD_HISTORY, (unsigned char *)hd, + 1033); + free(hd); + } + + return; +} + + +/* + * Parsing original app path to retrieve default bundle + * + * -1 : Invalid sequence + * -2 : Buffer overflow + * + */ +static inline int __parser(const char *arg, char *out, int out_size) +{ + register int i; + int state = 1; + char *start_out = out; + + if (arg == NULL || out == NULL) { + /* Handles null buffer*/ + return 0; + } + + for (i = 0; out_size > 1; i++) { + switch (state) { + case 1: + switch (arg[i]) { + case ' ': + case '\t': + state = 5; + break; + case '\0': + state = 7; + break; + case '\"': + state = 2; + break; + case '\\': + state = 4; + break; + default: + *out = arg[i]; + out++; + out_size--; + break; + } + break; + case 2: /* escape start*/ + switch (arg[i]) { + case '\0': + state = 6; + break; + case '\"': + state = 1; + break; + default: + *out = arg[i]; + out++; + out_size--; + break; + } + break; + case 4: /* character escape*/ + if (arg[i] == '\0') { + state = 6; + } else { + *out = arg[i]; + out++; + out_size--; + state = 1; + } + break; + case 5: /* token*/ + if (out != start_out) { + *out = '\0'; + out_size--; + return i; + } + i--; + state = 1; + break; + case 6: + return -1; /* error*/ + case 7: /* terminate*/ + *out = '\0'; + out_size--; + return 0; + default: + state = 6; + break; /* error*/ + } + } + + if (out_size == 1) { + *out = '\0'; + } + /* Buffer overflow*/ + return -2; +} + +_static_ void __modify_bundle(bundle * kb, int caller_pid, + app_info_from_db * menu_info, int cmd) +{ + // warning: unused parameter + caller_pid = caller_pid; + + bundle_del(kb, AUL_K_PKG_NAME); + bundle_del(kb, AUL_K_EXEC); + bundle_del(kb, AUL_K_PACKAGETYPE); + + /* Parse app_path to retrieve default bundle*/ + if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd == APP_RESUME) { + char *ptr; + char exe[MAX_PATH_LEN]; + int flag; + + ptr = _get_original_app_path(menu_info); + + flag = __parser(ptr, exe, sizeof(exe)); + if (flag > 0) { + char key[256]; + char value[256]; + + ptr += flag; + _D("parsing app_path: EXEC - %s\n", exe); + + do { + flag = __parser(ptr, key, sizeof(key)); + if (flag <= 0) + break; + ptr += flag; + + flag = __parser(ptr, value, sizeof(value)); + if (flag < 0) + break; + ptr += flag; + + /*bundle_del(kb, key);*/ + bundle_add(kb, key, value); + } while (flag > 0); + } else if (flag == 0) { + _D("parsing app_path: No arguments\n"); + } else { + _D("parsing app_path: Invalid argument\n"); + } + } +} + +_static_ int __child_raise_win_by_x(int pid, void *priv) +{ + // warning: unused parameter + priv = priv; + + return x_util_raise_win(pid); +} + +_static_ int __raise_win_by_x(int pid) +{ + int pgid; + if (x_util_raise_win(pid) == 0) + return 0; + + /* support app launched by shell script*/ + pgid = getpgid(pid); + _D("X raise failed. try to find first child & raise it - c:%d p:%d\n", + pgid, pid); + + if (pgid <= 1) + return -1; + if (__proc_iter_pgid(pgid, __child_raise_win_by_x, NULL) < 0) + return -1; + + return 0; +} + +_static_ int __send_to_sigkill(int pid) +{ + int pgid; + + pgid = getpgid(pid); + if (pgid <= 1) + return -1; + + if (killpg(pgid, SIGKILL) < 0) + return -1; + + return 0; +} + +_static_ int __term_app(int pid) +{ + int dummy; + if (__app_send_raw + (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) { + _D("terminate packet send error - use SIGKILL"); + if (__send_to_sigkill(pid) < 0) { + _E("fail to killing - %d\n", pid); + return -1; + } + } + _D("term done\n"); + return 0; +} + +_static_ int __resume_app(int pid) +{ + int dummy; + int ret; + if ((ret = + __app_send_raw(pid, APP_RESUME_BY_PID, (unsigned char *)&dummy, + sizeof(int))) < 0) { + if (ret == -EAGAIN) + _E("resume packet timeout error"); + else { + _D("resume packet send error - use raise win"); + if (__raise_win_by_x(pid) < 0) { + _E("raise failed - %d resume fail\n", pid); + _E("we will term the app - %d\n", pid); + __send_to_sigkill(pid); + ret = -1; + } else + ret = 0; + } + } + _D("resume done\n"); + return ret; +} + +static int __get_caller_pid(bundle *kb) +{ + const char *pid_str; + int pid; + + pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID); + if(pid_str) + goto end; + + pid_str = bundle_get_val(kb, AUL_K_CALLER_PID); + if (pid_str == NULL) + return -1; + +end: + pid = atoi(pid_str); + if (pid <= 1) + return -1; + + return pid; +} + +_static_ int __foward_cmd(int cmd, bundle *kb, int cr_pid) +{ + int pid; + char tmp_pid[MAX_PID_STR_BUFSZ]; + int datalen; + bundle_raw *kb_data; + int res; + + if ((pid = __get_caller_pid(kb)) < 0) + return AUL_R_ERROR; + + snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid); + + bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid); + + bundle_encode(kb, &kb_data, &datalen); + if ((res = __app_send_raw(pid, cmd, kb_data, datalen)) < 0) + res = AUL_R_ERROR; + + free(kb_data); + + return res; +} + +_static_ void __real_send(int clifd, int ret) +{ + if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) { + if (errno == EPIPE) { + _E("send failed due to EPIPE.\n"); + } + _E("send fail to client"); + } + + close(clifd); +} + +_static_ void __send_result_to_caller(int clifd, int ret) +{ + char *cmdline; + int wait_count; + int cmdline_changed = 0; + int cmdline_exist = 0; + + if (clifd == -1) + return; + + if (ret <= 1) { + __real_send(clifd, ret); + return; + } + /* check normally was launched?*/ + wait_count = 1; + do { + cmdline = __proc_get_cmdline_bypid(ret); + if (cmdline == NULL) { + _E("error founded when being launched with %d", ret); + + } else if (strcmp(cmdline, launchpad_cmdline)) { + free(cmdline); + cmdline_changed = 1; + break; + } else { + cmdline_exist = 1; + free(cmdline); + } + + _D("-- now wait to change cmdline --"); + usleep(50 * 1000); /* 50ms sleep*/ + wait_count++; + } while (wait_count <= 20); /* max 50*20ms will be sleep*/ + + if ((!cmdline_exist) && (!cmdline_changed)) { + __real_send(clifd, -1); /* abnormally launched*/ + return; + } + + if (!cmdline_changed) + _E("process launched, but cmdline not changed"); + + __real_send(clifd, ret); + return; +} + +static app_info_from_db *_get_app_info_from_bundle_by_pkgname( + const char *pkgname, bundle *kb) +{ + app_info_from_db *menu_info; + + menu_info = calloc(1, sizeof(app_info_from_db)); + if (menu_info == NULL) { + return NULL; + } + + menu_info->pkg_name = strdup(pkgname); + menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC)); + if (menu_info->app_path != NULL) + menu_info->original_app_path = strdup(menu_info->app_path); + menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE)); + + if (!_get_app_path(menu_info)) { + _free_app_info_from_db(menu_info); + return NULL; + } + + return menu_info; +} + +_static_ void __launchpad_main_loop(int main_fd) +{ + bundle *kb = NULL; + app_pkt_t *pkt = NULL; + app_info_from_db *menu_info = NULL; + + const char *pkg_name = NULL; + const char *app_path = NULL; + int pid = -1; + int clifd = -1; + struct ucred cr; + int is_real_launch = 0; + + char sock_path[UNIX_PATH_MAX] = {0,}; + + pkt = __app_recv_raw(main_fd, &clifd, &cr); + if (!pkt) { + _D("packet is NULL"); + goto end; + } + + kb = bundle_decode(pkt->data, pkt->len); + if (!kb) { + _D("bundle decode error"); + goto end; + } + + INIT_PERF(kb); + PERF("packet processing start"); + + pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME); + _D("pkg name : %s\n", pkg_name); + + menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb); + if (menu_info == NULL) { + _D("such pkg no found"); + goto end; + } + + app_path = _get_app_path(menu_info); + if(app_path == NULL) { + _E("app_path is NULL"); + goto end; + } + if (app_path[0] != '/') { + _D("app_path is not absolute path"); + goto end; + } + + __modify_bundle(kb, cr.pid, menu_info, pkt->cmd); + pkg_name = _get_pkgname(menu_info); + + PERF("get package information & modify bundle done"); + + { + pid = fork(); + if (pid == 0) { + PERF("fork done"); + _E("lock up test log(no error) : fork done"); + + close(clifd); + close(main_fd); + __signal_unset_sigchld(); + __signal_fini(); + + snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid()); + unlink(sock_path); + + PERF("prepare exec - first done"); + _E("lock up test log(no error) : prepare exec - first done"); + + if (__prepare_exec(pkg_name, app_path, + menu_info, kb) < 0) { + _E("preparing work fail to launch - " + "can not launch %s\n", pkg_name); + exit(-1); + } + + PERF("prepare exec - second done"); + _E("lock up test log(no error) : prepare exec - second done"); + + __real_launch(app_path, kb); + + exit(-1); + } + _D("==> real launch pid : %d %s\n", pid, app_path); + is_real_launch = 1; + } + + end: + __send_result_to_caller(clifd, pid); + + if (pid > 0) { + if (is_real_launch) { + /*TODO: retry*/ + __signal_block_sigchld(); + __send_app_launch_signal(pid); + __signal_unblock_sigchld(); + } + } + + if (menu_info != NULL) + _free_app_info_from_db(menu_info); + + if (kb != NULL) + bundle_free(kb); + if (pkt != NULL) + free(pkt); + + /* Active Flusing for Daemon */ + if (initialized > AUL_POLL_CNT) { + sqlite3_release_memory(SQLITE_FLUSH_MAX); + malloc_trim(0); + initialized = 1; + } + +} + +_static_ int __launchpad_pre_init(int argc, char **argv) +{ + int fd; + + /* signal init*/ + __signal_init(); + + /* get my(launchpad) command line*/ + launchpad_cmdline = __proc_get_cmdline_bypid(getpid()); + if (launchpad_cmdline == NULL) { + _E("launchpad cmdline fail to get"); + return -1; + } + _D("launchpad cmdline = %s", launchpad_cmdline); + + /* create launchpad sock */ + fd = __create_server_sock(WRT_LAUNCHPAD_PID); + if (fd < 0) { + _E("server sock error"); + return -1; + } + + __preload_init(argc, argv); + + __preload_init_for_wrt(); + + __preexec_init(argc, argv); + + return fd; +} + +_static_ int __launchpad_post_init() +{ + /* Setting this as a global variable to keep track + of launchpad poll cnt */ + /* static int initialized = 0;*/ + + if (initialized) { + initialized++; + return 0; + } + + if (__signal_set_sigchld() < 0) + return -1; + + initialized++; + + return 0; +} + +int main(int argc, char **argv) +{ + int main_fd; + struct pollfd pfds[POLLFD_MAX]; + int i; + + /* init without concerning X & EFL*/ + main_fd = __launchpad_pre_init(argc, argv); + if (main_fd < 0) { + _E("launchpad pre init failed"); + exit(-1); + } + + pfds[0].fd = main_fd; + pfds[0].events = POLLIN; + pfds[0].revents = 0; + + while (1) { + if (poll(pfds, POLLFD_MAX, -1) < 0) + continue; + + /* init with concerning X & EFL (because of booting + sequence problem)*/ + if (__launchpad_post_init() < 0) { + _E("launcpad post init failed"); + exit(-1); + } + + for (i = 0; i < POLLFD_MAX; i++) { + if ((pfds[i].revents & POLLIN) != 0) { + __launchpad_main_loop(pfds[i].fd); + } + } + } +} + diff --git a/src/wrt-launchpad-daemon/launchpad_src/sigchild.h b/src/wrt-launchpad-daemon/launchpad_src/sigchild.h new file mode 100644 index 0000000..2f56275 --- /dev/null +++ b/src/wrt-launchpad-daemon/launchpad_src/sigchild.h @@ -0,0 +1,258 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#include +#include "app_signal.h" + +static struct sigaction old_sigchild; +static DBusConnection *bus = NULL; +sigset_t oldmask; + +static inline void __socket_garbage_collector() +{ + DIR *dp; + struct dirent *dentry; + char tmp[MAX_LOCAL_BUFSZ]; + + dp = opendir(AUL_SOCK_PREFIX); + if (dp == NULL) + return; + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + snprintf(tmp, MAX_LOCAL_BUFSZ, "/proc/%s", dentry->d_name); + if (access(tmp, F_OK) < 0) { /* Flawfinder: ignore */ + snprintf(tmp, MAX_LOCAL_BUFSZ, "%s/%s", AUL_SOCK_PREFIX, + dentry->d_name); + unlink(tmp); + continue; + } + } + closedir(dp); +} + +static inline int __send_app_dead_signal(int dead_pid) +{ + DBusMessage *message; + + if (bus == NULL) + return -1; + + message = dbus_message_new_signal(AUL_DBUS_PATH, + AUL_DBUS_SIGNAL_INTERFACE, + AUL_DBUS_APPDEAD_SIGNAL); + + if (dbus_message_append_args(message, + DBUS_TYPE_UINT32, &dead_pid, + DBUS_TYPE_INVALID) == FALSE) { + _E("Failed to load data error"); + return -1; + } + + if (dbus_connection_send(bus, message, NULL) == FALSE) { + _E("dbus send error"); + return -1; + } + + dbus_connection_flush(bus); + dbus_message_unref(message); + + _D("send dead signal done\n"); + + return 0; +} + +static inline int __send_app_launch_signal(int launch_pid) +{ + DBusMessage *message; + + if (bus == NULL) + return -1; + + message = dbus_message_new_signal(AUL_DBUS_PATH, + AUL_DBUS_SIGNAL_INTERFACE, + AUL_DBUS_APPLAUNCH_SIGNAL); + + if (dbus_message_append_args(message, + DBUS_TYPE_UINT32, &launch_pid, + DBUS_TYPE_INVALID) == FALSE) { + _E("Failed to load data error"); + return -1; + } + + if (dbus_connection_send(bus, message, NULL) == FALSE) { + _E("dbus send error"); + return -1; + } + + dbus_connection_flush(bus); + dbus_message_unref(message); + + _D("send launch signal done\n"); + + return 0; +} + +static int __sigchild_action(void *data) +{ + pid_t dead_pid; + char buf[MAX_LOCAL_BUFSZ]; + + dead_pid = (pid_t) data; + if (dead_pid <= 0) + goto end; + + __send_app_dead_signal(dead_pid); + + snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, dead_pid); + unlink(buf); + + __socket_garbage_collector(); + end: + return 0; +} + +static void __launchpad_sig_child(int signo, siginfo_t *info, void *data) +{ + int status; + pid_t child_pid; + pid_t child_pgid; + + // warning: unused parameter + signo = signo; + data = data; + + child_pgid = getpgid(info->si_pid); + _D("dead_pid = %d pgid = %d", info->si_pid, child_pgid); + + while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { + if (child_pid == child_pgid) + killpg(child_pgid, SIGKILL); + __sigchild_action((void *)child_pid); + } + + return; +} + +static inline int __signal_init(void) +{ + int i; + for (i = 0; i < _NSIG; i++) { + switch (i) { + /* controlled by sys-assert package*/ + case SIGQUIT: + case SIGILL: + case SIGABRT: + case SIGBUS: + case SIGFPE: + case SIGSEGV: + case SIGPIPE: + break; + default: + signal(i, SIG_DFL); + break; + } + } + + return 0; +} + +static inline int __signal_set_sigchld(void) +{ + struct sigaction act; + DBusError error; + + dbus_error_init(&error); + dbus_threads_init_default(); + bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); + if (!bus) { + _E("Failed to connect to the D-BUS daemon: %s", error.message); + dbus_error_free(&error); + return -1; + } + /* TODO: if process stop mechanism is included, + should be modified (SA_NOCLDSTOP)*/ + act.sa_handler = NULL; + act.sa_sigaction = __launchpad_sig_child; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; + + if (sigaction(SIGCHLD, &act, &old_sigchild) < 0) + return -1; + + return 0; +} + +static inline int __signal_unset_sigchld(void) +{ + struct sigaction dummy; + + if (bus == NULL) + return 0; + + dbus_connection_close(bus); + if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0) + return -1; + + return 0; +} + +static inline int __signal_block_sigchld(void) +{ + sigset_t newmask; + + sigemptyset(&newmask); + sigaddset(&newmask, SIGCHLD); + + if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { + _E("SIG_BLOCK error"); + return -1; + } + + _D("SIGCHLD blocked"); + + return 0; +} + +static inline int __signal_unblock_sigchld(void) +{ + if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { + _E("SIG_SETMASK error"); + return -1; + } + + _D("SIGCHLD unblocked"); + return 0; +} + +static inline int __signal_fini(void) +{ +#ifndef PRELOAD_ACTIVATE + int i; + for (i = 0; i < _NSIG; i++) + signal(i, SIG_DFL); +#endif + return 0; +} + diff --git a/src/wrt-launchpad-daemon/launchpad_src/util_x.c b/src/wrt-launchpad-daemon/launchpad_src/util_x.c new file mode 100644 index 0000000..4e7ecd8 --- /dev/null +++ b/src/wrt-launchpad-daemon/launchpad_src/util_x.c @@ -0,0 +1,203 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#include +#include +#include +#include +#include + +#include +#include + +#include "simple_util.h" + +static Atom a_pid; +static int (*x_old_error) (Display *, XErrorEvent *); + + +static pid_t __get_win_pid(Display *d, Window win); +static int __find_win(Display *d, Window *win, pid_t pid); +static int __raise_win(Display *d, Window win); +static int __cb_x_error(Display *disp, XErrorEvent *ev); + +static pid_t __get_win_pid(Display *d, Window win) +{ + int r; + pid_t pid; + + Atom a_type; + int format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop_ret; + + retv_if(d == NULL || !a_pid, -1); + + prop_ret = NULL; + r = XGetWindowProperty(d, win, a_pid, 0, 1, False, XA_CARDINAL, + &a_type, &format, &nitems, &bytes_after, &prop_ret); + if (r != Success || prop_ret == NULL) + return -1; + + if (a_type == XA_CARDINAL && format == 32) + pid = *(unsigned long *)prop_ret; + else + pid = -1; + + XFree(prop_ret); + + return pid; +} + +static int __find_win(Display *d, Window *win, pid_t pid) +{ + int r; + pid_t p; + unsigned int n; + Window root, parent, *child; + + p = __get_win_pid(d, *win); + if (p == pid) + return 1; + + r = XQueryTree(d, *win, &root, &parent, &child, &n); + if (r) { + int i; + int found = 0; + + for (i = 0; i < n; i++) { + found = __find_win(d, &child[i], pid); + if (found) { + *win = child[i]; + break; + } + } + XFree(child); + + if (found) + return 1; + } + + return 0; +} + +static int __raise_win(Display *d, Window win) +{ + XWindowAttributes attr; + attr.map_state = IsUnmapped; + + XMapRaised(d, win); + + XGetWindowAttributes(d, win, &attr); + + if (attr.map_state == IsUnmapped) + _D("unmapped"); + else if (attr.map_state == IsUnviewable) + _D("unviewable"); + else if (attr.map_state == IsViewable) + _D("viewable"); + + retv_if(attr.map_state != IsViewable, -1); + + XSetInputFocus(d, win, RevertToPointerRoot, CurrentTime); + + return 0; +} + +int x_util_raise_win(pid_t pid) +{ + int r; + int found; + Display *d; + Window win; + + if (pid < 1) + return -1; + + r = kill(pid, 0); + if (r == -1) + return -1; + + d = XOpenDisplay(NULL); + retv_if(d == NULL, -1); + + win = XDefaultRootWindow(d); + + if (!a_pid) + a_pid = XInternAtom(d, "X_CLIENT_PID", True); + + found = __find_win(d, &win, pid); + if (!found) { + XCloseDisplay(d); + _E("cannot found window with pid - %d", pid); + return -1; + } + + r = __raise_win(d, win); + if (r < 0) + _E("fail to raise win"); + + XCloseDisplay(d); + + return r; +} + +int x_util_get_default_size(double *w, double *h) +{ + Display *d; + int screen_num; + + d = XOpenDisplay(NULL); + if (d == NULL) + return -1; + + screen_num = DefaultScreen(d); + + *w = DisplayWidth(d, screen_num); + *h = DisplayHeight(d, screen_num); + + _D("Root Width = %lf, Height = %lf\n", *w, *h); + + XCloseDisplay(d); + + return 0; +} + +static int __cb_x_error(Display *disp, XErrorEvent *ev) +{ + _E("X error received - Error Code = %d", ev->error_code); + return 0; +} + +int x_util_init() +{ + x_old_error = XSetErrorHandler(__cb_x_error); + return 0; +} + +int x_util_fini() +{ + XSetErrorHandler(x_old_error); + return 0; +} + diff --git a/src/wrt-launchpad-daemon/launchpad_src/util_x.h b/src/wrt-launchpad-daemon/launchpad_src/util_x.h new file mode 100644 index 0000000..650bad5 --- /dev/null +++ b/src/wrt-launchpad-daemon/launchpad_src/util_x.h @@ -0,0 +1,32 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef __UTIL_X_H_ +#define __UTIL_X_H_ + +int x_util_init(); +int x_util_fini(); +int x_util_get_default_size(double *w, double *h); +int x_util_raise_win(pid_t pid); + +#endif + diff --git a/src/wrt-launchpad-daemon/legacy/preload.h b/src/wrt-launchpad-daemon/legacy/preload.h new file mode 100644 index 0000000..b04c14a --- /dev/null +++ b/src/wrt-launchpad-daemon/legacy/preload.h @@ -0,0 +1,171 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifdef PRELOAD_ACTIVATE + +#include +#define PRELOAD_FILE SHARE_PREFIX"/preload_list.txt" +#define PRELOAD_FILE_WRT SHARE_PREFIX"/preload_list_wrt.txt" + +#define EFL_PREINIT_FUNC "elm_quicklaunch_init" +#define EFL_SHUTDOWN_FUNC "elm_quicklaunch_shutdown" + +static int preload_initialized = 0; +static int g_argc; +static char **g_argv; +static size_t max_cmdline_size = 0; + +static int (*dl_einit) () = NULL; +static int (*dl_efini) () = NULL; + +static inline void __preload_init(int argc, char **argv) +{ + void *handle = NULL; + char soname[MAX_LOCAL_BUFSZ]; + FILE *preload_list; + int (*func)() = NULL; + int i; + + g_argc = argc; + g_argv = argv; + for (i = 0; i < argc; i++) { + max_cmdline_size += (strlen(argv[i]) + 1); + } + _D("max_cmdline_size = %d", max_cmdline_size); + + preload_list = fopen(PRELOAD_FILE, "rt"); + if (preload_list == NULL) { + _E("no preload\n"); + return; + } + + while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > (char*)0) { + soname[strlen(soname) - 1] = 0; + handle = dlopen(soname, RTLD_NOW); + if (handle == NULL) + continue; + _D("preload %s# - handle : %x\n", soname, handle); + + func = dlsym(handle, EFL_PREINIT_FUNC); + if (func != NULL) { + _D("get pre-initialization function\n"); + dl_einit = func; + func = dlsym(handle, EFL_SHUTDOWN_FUNC); + if (func != NULL) { + _D("get shutdown function\n"); + dl_efini = func; + } + } + } + + fclose(preload_list); + preload_initialized = 1; +} + +static inline int preinit_init() +{ + if (dl_einit != NULL) + dl_einit(0, NULL); + _D("pre-initialzation on"); + return 0; +} + +static inline int preinit_fini() +{ + if (dl_efini != NULL) + dl_efini(); + _D("pre-initialization off"); + return 0; +} + +/* TODO : how to set cmdline gracefully ?? */ +static inline int __change_cmdline(char *cmdline) +{ + if (strlen(cmdline) > max_cmdline_size + 1) { + _E("cmdline exceed max size : %d", max_cmdline_size); + return -1; + } + + memset(g_argv[0], '\0', max_cmdline_size); + snprintf(g_argv[0], max_cmdline_size, "%s", cmdline); + + return 0; +} + +static inline void __preload_exec(int argc, char **argv) +{ + void *handle = NULL; + int (*dl_main) (int, char **); + + if (!preload_initialized) + return; + + handle = dlopen(argv[0], RTLD_LAZY | RTLD_GLOBAL); + if (handle == NULL) { + return; + } + + dl_main = dlsym(handle, "main"); + if (dl_main != NULL) { + if (__change_cmdline(argv[0]) < 0) { + _E("change cmdline fail"); + return; + } + dl_main(argc, argv); + } else { + _E("dlsym not founded. bad preloaded app - check fpie pie"); + } + + exit(0); +} + +static inline void __preload_init_for_wrt() +{ + void *handle = NULL; + char soname[MAX_LOCAL_BUFSZ]; + FILE *preload_list; + + preload_list = fopen(PRELOAD_FILE_WRT, "rt"); + if (preload_list == NULL) { + _E("no wrt preload\n"); + return; + } + + while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > (char*)0) { + soname[strlen(soname) - 1] = 0; + handle = dlopen(soname, RTLD_NOW|RTLD_GLOBAL); + if (handle == NULL) + continue; + _D("preload %s# - handle : %x\n", soname, handle); + } + + fclose(preload_list); +} + +#else + +static inline void __preload_init(int argc, char **argv); +static inline void __preload_exec(int argc, char **argv); +static inline void __preload_init_for_wrt(); + +#endif + diff --git a/src/wrt-launchpad-daemon/legacy/preload_list_wrt.txt b/src/wrt-launchpad-daemon/legacy/preload_list_wrt.txt new file mode 100644 index 0000000..01635cd --- /dev/null +++ b/src/wrt-launchpad-daemon/legacy/preload_list_wrt.txt @@ -0,0 +1,2 @@ +/usr/bin/wrt-client +/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so \ No newline at end of file diff --git a/src/wrt-launchpad-daemon/src/app_sock.c b/src/wrt-launchpad-daemon/src/app_sock.c new file mode 100644 index 0000000..b70fb38 --- /dev/null +++ b/src/wrt-launchpad-daemon/src/app_sock.c @@ -0,0 +1,406 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "app_sock.h" +#include "simple_util.h" + +static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen, + int nsec); + + +static inline void __set_sock_option(int fd, int cli) +{ + int size; + struct timeval tv = { 3, 200 * 1000 }; /* 3.2 sec */ + + size = AUL_SOCK_MAXBUFF; + setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); + if (cli) + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); +} + +int __create_server_sock(int pid) +{ + struct sockaddr_un saddr; + struct sockaddr_un p_saddr; + int fd; + mode_t orig_mask; + + /* Create basedir for our sockets */ + orig_mask = umask(0); + mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX); + umask(orig_mask); + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + /* support above version 2.6.27*/ + if (fd < 0) { + if (errno == EINVAL) { + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + _E("second chance - socket create error"); + return -1; + } + } else { + _E("socket error"); + return -1; + } + } + + bzero(&saddr, sizeof(saddr)); + saddr.sun_family = AF_UNIX; + snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid); + unlink(saddr.sun_path); + + /* labeling to socket for SMACK */ + if(getuid() == 0) { // this is meaningful iff current user is ROOT + if(smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) { + /* in case of unsupported filesystem on 'socket' */ + /* or permission error by using 'emulator', bypass*/ + if((errno != EOPNOTSUPP) && (errno != EPERM)) { + _E("labeling to socket(IPOUT) error"); + return -1; + } + } + if(smack_fsetlabel(fd, "*", SMACK_LABEL_IPIN) != 0) { + /* in case of unsupported filesystem on 'socket' */ + /* or permission error by using 'emulator', bypass*/ + if((errno != EOPNOTSUPP) && (errno != EPERM)) { + _E("labeling to socket(IPIN) error"); + return -1; + } + } + } + + if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { + _E("bind error"); + return -1; + } + + if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + /* Flawfinder: ignore*/ + _E("failed to change the socket permission"); + return -1; + } + + __set_sock_option(fd, 0); + + if (listen(fd, 10) == -1) { + _E("listen error"); + return -1; + } + + /* support app launched by shell script */ + if (pid != WRT_LAUNCHPAD_PID) { + int pgid; + pgid = getpgid(pid); + if (pgid > 1) { + snprintf(p_saddr.sun_path, UNIX_PATH_MAX, "%s/%d", + AUL_SOCK_PREFIX, pgid); + if (link(saddr.sun_path, p_saddr.sun_path) < 0) { + if (errno == EEXIST) + _D("pg path - already exists"); + else + _E("pg path - unknown create error"); + } + } + } + + return fd; +} + +int __create_client_sock(int pid) +{ + int fd = -1; + struct sockaddr_un saddr = { 0, }; + int retry = 1; + int ret = -1; + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + /* support above version 2.6.27*/ + if (fd < 0) { + if (errno == EINVAL) { + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + _E("second chance - socket create error"); + return -1; + } + } else { + _E("socket error"); + return -1; + } + } + + saddr.sun_family = AF_UNIX; + snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid); + retry_con: + ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr), + 100 * 1000); + if (ret < -1) { + _E("maybe peer not launched or peer daed\n"); + if (retry > 0) { + usleep(100 * 1000); + retry--; + goto retry_con; + } + } + if (ret < 0) { + close(fd); + return -1; + } + + __set_sock_option(fd, 1); + + return fd; +} + +static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen, + int nsec) +{ + int flags; + int ret; + int error; + socklen_t len; + fd_set readfds; + fd_set writefds; + struct timeval timeout; + + flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + error = 0; + if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) { + if (errno != EAGAIN && errno != EINPROGRESS) { + fcntl(fd, F_SETFL, flags); + return (-2); + } + } + + /* Do whatever we want while the connect is taking place. */ + if (ret == 0) + goto done; /* connect completed immediately */ + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + writefds = readfds; + timeout.tv_sec = 0; + timeout.tv_usec = nsec; + + if ((ret = select(fd + 1, &readfds, &writefds, NULL, + nsec ? &timeout : NULL)) == 0) { + close(fd); /* timeout */ + errno = ETIMEDOUT; + return (-1); + } + + if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) { + len = sizeof(error); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) + return (-1); /* Solaris pending error */ + } else + return (-1); /* select error: sockfd not set*/ + + done: + fcntl(fd, F_SETFL, flags); + if (error) { + close(fd); + errno = error; + return (-1); + } + return (0); +} + +/** + * @brief Send data (in raw) to the process with 'pid' via socket + */ +int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen) +{ + int fd; + int len; + int res = 0; + app_pkt_t *pkt = NULL; + + if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) { + _E("keybundle error\n"); + return -EINVAL; + } + + fd = __create_client_sock(pid); + if (fd < 0) + return -ECOMM; + + pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); + if (NULL == pkt) { + _E("Malloc Failed!"); + return -ENOMEM; + } + memset(pkt, 0, AUL_SOCK_MAXBUFF); + + pkt->cmd = cmd; + pkt->len = datalen; + memcpy(pkt->data, kb_data, datalen); + + if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) { + _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno); + if (errno == EPIPE) { + _E("pid:%d, fd:%d\n", pid, fd); + } + close(fd); + if (pkt) { + free(pkt); + pkt = NULL; + } + return -ECOMM; + } + if (pkt) { + free(pkt); + pkt = NULL; + } + + len = recv(fd, &res, sizeof(int), 0); + if (len == -1) { + if (errno == EAGAIN) { + _E("recv timeout \n"); + res = -EAGAIN; + } else { + _E("recv error\n"); + res = -ECOMM; + } + } + close(fd); + + return res; +} + +app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr) +{ + int len; + struct sockaddr_un aul_addr = { 0, }; + int sun_size; + app_pkt_t *pkt = NULL; + int cl = sizeof(struct ucred); + + sun_size = sizeof(struct sockaddr_un); + + if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr, + (socklen_t *) &sun_size)) == -1) { + if (errno != EINTR) + _E("accept error"); + return NULL; + } + + if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr, + (socklen_t *) &cl) < 0) { + _E("peer information error"); + close(*clifd); + return NULL; + } + + pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); + if(pkt == NULL) { + close(*clifd); + return NULL; + } + memset(pkt, 0, AUL_SOCK_MAXBUFF); + + __set_sock_option(*clifd, 1); + + retry_recv: + /* receive single packet from socket */ + len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0); + if (len < 0) + if (errno == EINTR) + goto retry_recv; + + if ((len < 8) || (len != (pkt->len + 8))) { + _E("recv error %d %d", len, pkt->len); + free(pkt); + close(*clifd); + return NULL; + } + + return pkt; +} + +app_pkt_t *__app_send_cmd_with_result(int pid, int cmd) +{ + int fd; + int len; + app_pkt_t *pkt = NULL; + + fd = __create_client_sock(pid); + if (fd < 0) + return NULL; + + pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); + if (NULL == pkt) { + _E("Malloc Failed!"); + return NULL; + } + memset(pkt, 0, AUL_SOCK_MAXBUFF); + + pkt->cmd = cmd; + pkt->len = 0; + + if ((len = send(fd, pkt, 8, 0)) != 8) { + _E("sendto() failed - %d", len); + if (errno == EPIPE) { + _E("pid:%d, fd:%d\n", pid, fd); + } + close(fd); + + free(pkt); + return NULL; + } + +retry_recv: + /* receive single packet from socket */ + len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0); + if (len == -1) { + if (errno == EAGAIN) { + _E("recv timeout \n"); + free(pkt); + return NULL; + } else if (errno == EINTR) { + goto retry_recv; + } else { + _E("recv error %s\n", strerror(errno)); + free(pkt); + return NULL; + } + } else + _D("recv result = %d", len); + close(fd); + + return pkt; +} + + diff --git a/src/wrt-launchpad-daemon/src/simple_util.c b/src/wrt-launchpad-daemon/src/simple_util.c new file mode 100644 index 0000000..d5bbeda --- /dev/null +++ b/src/wrt-launchpad-daemon/src/simple_util.c @@ -0,0 +1,210 @@ +/* + * aul + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include "simple_util.h" + +#define BINSH_NAME "/bin/sh" +#define BINSH_SIZE 7 + +#define PROC_STAT_GID_POS 5 + + +static inline int __read_proc(const char *path, char *buf, int size); +static inline int __find_pid_by_cmdline(const char *dname, + const char *cmdline, void *priv); +static inline int __get_pgid_from_stat(int pid); + + +static inline int __read_proc(const char *path, char *buf, int size) +{ + int fd; + int ret; + + if (buf == NULL || path == NULL) + return -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + return -1; + + ret = read(fd, buf, size - 1); + if (ret <= 0) { + close(fd); + return -1; + } else + buf[ret] = 0; + + close(fd); + + return ret; +} + +static inline int __find_pid_by_cmdline(const char *dname, + const char *cmdline, void *priv) +{ + char *apppath; + int pid = 0; + + apppath = (char *)priv; + if (strncmp(cmdline, apppath, MAX_LOCAL_BUFSZ-1) == 0) { + pid = atoi(dname); + if (pid != getpgid(pid)) + pid = 0; + } + + return pid; +} + +int __proc_iter_cmdline( + int (*iterfunc)(const char *dname, const char *cmdline, void *priv), + void *priv) +{ + DIR *dp; + struct dirent *dentry; + int pid; + int ret; + char buf[MAX_LOCAL_BUFSZ]; + + dp = opendir("/proc"); + if (dp == NULL) { + return -1; + } + + if (iterfunc == NULL) + iterfunc = __find_pid_by_cmdline; + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry->d_name); + ret = __read_proc(buf, buf, sizeof(buf)); + if (ret <= 0) + continue; + + /* support app launched by shell script*/ + if (strncmp(buf, BINSH_NAME, BINSH_SIZE) == 0) + pid = + iterfunc(dentry->d_name, &buf[BINSH_SIZE + 1], + priv); + else + pid = iterfunc(dentry->d_name, buf, priv); + + if (pid > 0) { + closedir(dp); + return pid; + } + } + + closedir(dp); + return -1; +} + +char *__proc_get_cmdline_bypid(int pid) +{ + char buf[MAX_LOCAL_BUFSZ]; + int ret; + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + ret = __read_proc(buf, buf, sizeof(buf)); + if (ret <= 0) + return NULL; + + /* support app launched by shell script*/ + if (strncmp(buf, BINSH_NAME, BINSH_SIZE) == 0) + return strdup(&buf[BINSH_SIZE + 1]); + else + return strdup(buf); +} + +static inline int __get_pgid_from_stat(int pid) +{ + char buf[MAX_LOCAL_BUFSZ]; + char *str; + int ret; + int i; + int count = 0; + + if (pid <= 1) + return -1; + + snprintf(buf, sizeof(buf), "/proc/%d/stat", pid); + ret = __read_proc(buf, buf, sizeof(buf)); + if (ret < 0) + return -1; + + for (i = 0; i < (ret - 1); i++) { + if (buf[i] == ' ') { + count++; + if (count == PROC_STAT_GID_POS - 1) + str = &(buf[i + 1]); + else if (count == PROC_STAT_GID_POS) { + buf[i] = 0; + break; + } + } + } + + if (count == PROC_STAT_GID_POS) + pid = atoi(str); + else + pid = -1; + + return pid; +} + +int __proc_iter_pgid(int pgid, int (*iterfunc) (int pid, void *priv), + void *priv) +{ + DIR *dp; + struct dirent *dentry; + int _pgid; + int ret = -1; + + dp = opendir("/proc"); + if (dp == NULL) { + return -1; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + _pgid = __get_pgid_from_stat(atoi(dentry->d_name)); + if (pgid == _pgid) { + ret = iterfunc(atoi(dentry->d_name), priv); + if (ret >= 0) + break; + } + } + + closedir(dp); + return ret; +} + diff --git a/src/wrt-launchpad-daemon/wrt_launchpad_run.sh b/src/wrt-launchpad-daemon/wrt_launchpad_run.sh new file mode 100644 index 0000000..1c35f19 --- /dev/null +++ b/src/wrt-launchpad-daemon/wrt_launchpad_run.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/bin/wrt_launchpad_daemon " " & diff --git a/wrt-engine.map b/wrt-engine.map index aac9eaf..59c84e5 100644 --- a/wrt-engine.map +++ b/wrt-engine.map @@ -17,6 +17,7 @@ }; UG_MODULE_INIT; UG_MODULE_EXIT; + main; local: *; }; -- 2.7.4