* 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
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
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
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}
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
%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/*
--- /dev/null
+[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
IF(PROFILING)
ADD_SUBDIRECTORY(profiling)
ENDIF(PROFILING)
+ADD_SUBDIRECTORY(wrt-launchpad-daemon)
TARGET_LINK_LIBRARIES(${TARGET_WRT_CLIENT}
${CLIENT_DEP_LIBRARIES}
${TARGET_CORE_MODULE_LIB}
+ "-pie"
)
SET_TARGET_PROPERTIES(${TARGET_WRT_CLIENT} PROPERTIES
--- /dev/null
+# 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 )
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <dlfcn.h>
+#include <glib.h>
+#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
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#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
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <unistd.h>
+#define __USE_GNU
+#include <sys/socket.h>
+#include <linux/un.h>
+
+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
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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
+
+
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <ail.h>
+#include <string.h>
+#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;
+
+}
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <sys/time.h>
+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
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <unistd.h>
+#include <ctype.h>
+#include <dlog.h>
+
+#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
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <privilege-control.h>
+
+#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
+
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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*/
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <X11/Xlib.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <poll.h>
+#include <sys/prctl.h>
+#include <malloc.h>
+
+#include "app_sock.h"
+#include <aul.h>
+
+#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 <app-checker.h>
+#include <sqlite3.h>
+
+#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);
+ }
+ }
+ }
+}
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <pthread.h>
+#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;
+}
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#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;
+}
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <dlfcn.h>
+#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
+
--- /dev/null
+/usr/bin/wrt-client
+/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so
\ No newline at end of file
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/smack.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#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;
+}
+
+
--- /dev/null
+/*
+ * aul
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+ *
+ * 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 <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <stdio.h>
+#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;
+}
+
--- /dev/null
+#!/bin/sh
+
+/usr/bin/wrt_launchpad_daemon " " &
};
UG_MODULE_INIT;
UG_MODULE_EXIT;
+ main;
local: *;
};