initial release
authorJaeho Lee <jaeho81.lee@samsung.com>
Thu, 30 May 2013 08:14:21 +0000 (17:14 +0900)
committerJaeho Lee <jaeho81.lee@samsung.com>
Thu, 30 May 2013 08:15:12 +0000 (17:15 +0900)
Signed-off-by: Jaeho Lee <jaeho81.lee@samsung.com>
Change-Id: If2a3f89df7ef1bea6e960dd2a0ed350d9c873020

18 files changed:
CMakeLists.txt [new file with mode: 0755]
feature/preexec.h [new file with mode: 0755]
include/access_control.h [new file with mode: 0755]
include/app_signal.h [new file with mode: 0755]
include/app_sock.h [new file with mode: 0755]
include/aul_util.h [new file with mode: 0755]
include/menu_db_util.h [new file with mode: 0755]
include/perf.h [new file with mode: 0755]
include/preload.h [new file with mode: 0755]
include/simple_util.h [new file with mode: 0755]
packaging/debug-launchpad.spec [new file with mode: 0644]
src/app_sock.c [new file with mode: 0755]
src/config.h [new file with mode: 0755]
src/gl.h [new file with mode: 0755]
src/heap_dbg.h [new file with mode: 0755]
src/launchpad.c [new file with mode: 0755]
src/sigchild.h [new file with mode: 0755]
src/simple_util.c [new file with mode: 0755]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..0791cd6
--- /dev/null
@@ -0,0 +1,87 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
+
+PROJECT(debug-launchpad C)
+SET(VERSION_MAJOR 0)
+SET(VERSION "${VERSION_MAJOR}.1.0")
+
+### Global setting ###
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+
+# Build type : Release
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+       SET(CMAKE_BUILD_TYPE "Release")
+ENDIF()
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+
+# Set required packages
+INCLUDE(FindPkgConfig)
+
+pkg_check_modules(pkgs REQUIRED dlog x11 libprivilege-control dbus-glib-1 sqlite3 bundle vconf libsmack aul)
+
+FIND_LIBRARY(LIB_DL dl)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+# Compiler flags
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/feature)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fpic")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TEST_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+
+SET(CMAKE_SKIP_BUILD_RPATH true)
+
+# Get uname value to set 'TARGET' definition 
+# TODO: Is this needed?
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+IF("${ARCH}" STREQUAL "arm")
+       ADD_DEFINITIONS("-DTARGET")
+       MESSAGE("add -DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
+ADD_DEFINITIONS("-DSHARE_PREFIX=\"/usr/share/aul\"")
+
+# Linker flags
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+
+
+### Build ###
+
+# launchpad(old avatar) daemon
+SET(AVATAR_NAME "debug_launchpad_preloading_preinitializing_daemon")
+add_executable(${AVATAR_NAME}
+       src/app_sock.c
+       src/simple_util.c
+       src/launchpad.c
+       )
+
+MESSAGE("       "${pkgs_LDFLAGS})
+target_link_libraries(${AVATAR_NAME} aul ${pkgs_LDFLAGS} ${LIB_DL})
+set_target_properties(${AVATAR_NAME}
+               PROPERTIES SKIP_BUILD_RPATH true
+               ) # remove rpath option that is automatically generated by cmake.
+
+
+INSTALL(TARGETS ${LAUNCH_AGENT} DESTINATION bin)
+
+
+
+# pkgconfig file
+
+
+### Install ###
+INSTALL(TARGETS ${AVATAR_NAME} DESTINATION bin)
+
+
diff --git a/feature/preexec.h b/feature/preexec.h
new file mode 100755 (executable)
index 0000000..1b567c4
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ *  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);
+       preexec_initialized = 0;
+       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;
+
+       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) > 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();
+                       fclose(preexec_file);
+                       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);
+                       handle = NULL;
+                       continue;
+               }
+
+               type_t->pkg_type = strdup(type);
+               if (type_t->pkg_type == NULL) {
+                       _E("no available memory\n");
+                       free(type_t);
+                       __preexec_list_free();
+                       fclose(preexec_file);
+                       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();
+                       fclose(preexec_file);
+                       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 void __preexec_list_free()
+{
+}
+
+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/include/access_control.h b/include/access_control.h
new file mode 100755 (executable)
index 0000000..6ba035c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  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
+
+
diff --git a/include/app_signal.h b/include/app_signal.h
new file mode 100755 (executable)
index 0000000..b30cb51
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  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 "org.tizen.aul.signal"
+#define AUL_DBUS_APPDEAD_SIGNAL        "app_dead"
+#define AUL_DBUS_APPLAUNCH_SIGNAL      "app_launch"
+
+#endif
diff --git a/include/app_sock.h b/include/app_sock.h
new file mode 100755 (executable)
index 0000000..a86867e
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  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_GET_APPID_BYPID,
+       APP_GET_APPID_BYPID_OK,
+       APP_GET_APPID_BYPID_ERROR,
+       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 DEBUG_LAUNCHPAD_PID -4
+#define ELOCALLAUNCH_ID 128
+#define EILLEGALACCESS 127
+#define ETERMINATING 126
+
+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);
+int __app_send_raw_with_noreply(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, unsigned char *kb_data, int datalen);
+
+
+#endif
+
diff --git a/include/aul_util.h b/include/aul_util.h
new file mode 100755 (executable)
index 0000000..e4c4630
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  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
+
+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/include/menu_db_util.h b/include/menu_db_util.h
new file mode 100755 (executable)
index 0000000..4bf2c21
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ *  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 <stdio.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 */
+       char *hwacc;            /* hwacceleration */
+} app_info_from_db;
+
+static inline char *_get_pkgname(app_info_from_db *menu_info)
+{
+       return menu_info ? menu_info->pkg_name : NULL;
+}
+
+static inline char *_get_app_path(app_info_from_db *menu_info)
+{
+       int i = 0;
+       int path_len = -1;
+
+       if (!menu_info || 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)
+{
+       return menu_info ? menu_info->original_app_path : NULL;
+}
+
+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);
+               if (menu_info->hwacc != NULL)
+                       free(menu_info->hwacc);
+               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_cb_ret_e ret = AIL_CB_RET_CONTINUE;
+
+       if (!menu_info)
+               return ret;
+
+       ail_appinfo_get_str(appinfo, AIL_PROP_PACKAGE_STR, &package);
+       if (package) {
+               menu_info->pkg_name = strdup(package);
+               ret = AIL_CB_RET_CANCEL;
+       }
+
+       return ret;
+}
+
+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/include/perf.h b/include/perf.h
new file mode 100755 (executable)
index 0000000..fb2582f
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  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
+
diff --git a/include/preload.h b/include/preload.h
new file mode 100755 (executable)
index 0000000..2af9468
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *  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 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 int 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) > 0) {
+               soname[strlen(soname) - 1] = 0;
+               handle = dlopen((const char *) 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);
+}
+
+#else
+
+static inline void __preload_init();
+static inline void __preload_exec(int argc, char **argv);
+
+#endif
+
diff --git a/include/simple_util.h b/include/simple_util.h
new file mode 100755 (executable)
index 0000000..e6eb5ee
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  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 "AUL_PAD"
+#else
+#undef LOG_TAG
+#define LOG_TAG "AUL"
+#endif
+#ifdef AMD_LOG
+#undef LOG_TAG
+#define LOG_TAG "AUL_AMD"
+#endif
+
+
+#define MAX_LOCAL_BUFSZ 128
+#define MAX_PID_STR_BUFSZ 20
+
+#define _E(fmt, arg...) LOGE(fmt, ##arg)
+#define _D(fmt, arg...) LOGD(fmt, ##arg)
+#define _W(fmt, arg...) LOGW(fmt, ##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/packaging/debug-launchpad.spec b/packaging/debug-launchpad.spec
new file mode 100644 (file)
index 0000000..3bed74f
--- /dev/null
@@ -0,0 +1,44 @@
+Name:       debug-launchpad
+Summary:    Debug Launchpad
+Version:    0.0.1
+Release:    1
+Group:      System/Libraries
+License:    Apache License, Version 2.0
+Source0:    %{name}-%{version}.tar.gz
+
+Requires(post): /sbin/ldconfig
+Requires(post): /usr/bin/systemctl
+Requires(postun): /sbin/ldconfig
+Requires(postun): /usr/bin/systemctl
+Requires(preun): /usr/bin/systemctl
+
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(dbus-glib-1)
+BuildRequires:  pkgconfig(sqlite3)
+BuildRequires:  pkgconfig(x11)
+BuildRequires:  pkgconfig(bundle)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(libprivilege-control)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(libsmack)
+BuildRequires:  pkgconfig(aul)
+
+
+%description
+Debug launchpad
+
+%prep
+%setup -q
+
+%build
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%post
+
+%files
+%{_bindir}/debug_launchpad_preloading_preinitializing_daemon
diff --git a/src/app_sock.c b/src/app_sock.c
new file mode 100755 (executable)
index 0000000..93b6f12
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ *  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);
+       (void) 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;
+               }
+       }
+
+       memset(&saddr, 0, 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");
+                               close(fd);
+                               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");
+                               close(fd);
+                               return -1;
+                       }
+               }
+       }
+
+       if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
+               _E("bind error");
+               close(fd);
+               return -1;
+       }
+
+       if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
+               /* Flawfinder: ignore*/
+               _E("failed to change the socket permission");
+               close(fd);
+               return -1;
+       }
+
+       __set_sock_option(fd, 0);
+
+       if (listen(fd, 128) == -1) {
+               _E("listen error");
+               close(fd);
+               return -1;
+       }
+
+       /* support app launched by shell script */
+       /*if (pid != 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:
+       (void) 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 ret;
+       int res = 0;
+       app_pkt_t *pkt = NULL;
+
+       if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
+               _E("keybundle error\n");
+               return -EINVAL;
+       }
+
+       _D("pid(%d) : cmd(%d)", pid, cmd);
+
+       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(len > 0) {
+                       while (len != datalen + 8) {
+                               ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
+                               if (ret < 0) {
+                                       _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
+                                       if (errno == EPIPE) {
+                                               _E("pid:%d, fd:%d\n", pid, fd);
+                                       }
+                                       close(fd);
+                                       if (pkt) {
+                                               free(pkt);
+                                               pkt = NULL;
+                                       }
+                                       return -ECOMM;
+                               }
+                               len += ret;
+                               _D("sendto() len - %d %d", len, datalen + 8);
+                       }
+               } else {
+                       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;
+}
+
+int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen)
+{
+       int fd;
+       int len;
+       int ret;
+       int res = 0;
+       app_pkt_t *pkt = NULL;
+
+       if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
+               _E("keybundle error\n");
+               return -EINVAL;
+       }
+
+       _D("pid(%d) : cmd(%d)", pid, cmd);
+
+       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(len > 0) {
+                       while (len != datalen + 8) {
+                               ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
+                               if (ret < 0) {
+                                       _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
+                                       if (errno == EPIPE) {
+                                               _E("pid:%d, fd:%d\n", pid, fd);
+                                       }
+                                       close(fd);
+                                       if (pkt) {
+                                               free(pkt);
+                                               pkt = NULL;
+                                       }
+                                       return -ECOMM;
+                               }
+                               len += ret;
+                               _D("sendto() len - %d %d", len, datalen + 8);
+                       }
+               } else {
+                       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;
+       }
+
+       close(fd);
+
+       return res;
+}
+
+app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
+{
+       int len;
+       int ret;
+       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) {
+               _E("recv error %d %d", len, pkt->len);
+               free(pkt);
+               close(*clifd);
+               return NULL;
+       }
+
+       while( len != (pkt->len + 8) ) {
+               ret = recv(*clifd, &pkt->data[len-8], AUL_SOCK_MAXBUFF, 0);
+               if (ret < 0) {
+                       _E("recv error %d %d", len, pkt->len);
+                       free(pkt);
+                       close(*clifd);
+                       return NULL;
+               }
+               len += ret;
+               _D("recv len %d %d", len, pkt->len);
+       }
+
+       return pkt;
+}
+
+app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen)
+{
+       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 = datalen;
+       if(kb_data) {
+               memcpy(pkt->data, kb_data, datalen);
+       }
+
+       if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 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);
+                       close(fd);
+                       return NULL;
+               } else if (errno == EINTR) {
+                       goto retry_recv;
+               } else {
+                       _E("recv error %s\n", strerror(errno));
+                       free(pkt);
+                       close(fd);
+                       return NULL;
+               }
+       } else
+               _D("recv result  = %d", len);
+       close(fd);
+
+       return pkt;
+}
+
+
diff --git a/src/config.h b/src/config.h
new file mode 100755 (executable)
index 0000000..f5728cf
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  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*/
+
diff --git a/src/gl.h b/src/gl.h
new file mode 100755 (executable)
index 0000000..4add496
--- /dev/null
+++ b/src/gl.h
@@ -0,0 +1,32 @@
+/*
+ *  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
+
diff --git a/src/heap_dbg.h b/src/heap_dbg.h
new file mode 100755 (executable)
index 0000000..7b6c718
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  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 <malloc.h>
+#include <stdio.h>
+#include <signal.h>
+
+#ifdef HEAPDGB_ACTIVATE
+
+#define HOOK_RESET()   \
+do {\
+       __malloc_hook = old_malloc_hook; \
+       __free_hook = old_free_hook;    \
+} while (0);
+
+#define HOOK_SET()     \
+do {\
+       __malloc_hook = my_malloc;      \
+       __free_hook = my_free;          \
+} while (0);
+
+static void *(*old_malloc_hook) (size_t size, const void *caller);
+static void *(*old_realloc_hook) (void *ptr, size_t size, const void *caller);
+static void (*old_free_hook) (void *ptr, const void *caller);
+
+static void *my_malloc(size_t size, const void *caller);
+static void *my_realloc(void *ptr, size_t size, const void *caller);
+static void my_free(void *ptr, const void *caller);
+
+static void my_free(void *ptr, const void *caller)
+{
+       void *callstack_addrs[20];
+       char **callstack_strings;
+       int i;
+
+       HOOK_RESET();
+
+       printf("%c[1;31m[FREE] %x %x", 27, ptr, caller);
+       printf("%c[0m\n", 27);
+       free(ptr);
+
+       HOOK_SET();
+
+}
+
+static void *my_malloc(size_t size, const void *caller)
+{
+       void *ptr;
+
+       HOOK_RESET();
+
+       ptr = malloc(size);
+       printf("%c[1;31m[MALLOC] %x %x", 27, ptr, caller);
+       printf("%c[0m\n", 27);
+
+       HOOK_SET();
+
+       return ptr;
+}
+
+static void malloc_init(void)
+{
+       old_malloc_hook = __malloc_hook;
+       old_free_hook = __free_hook;
+
+       HOOK_SET();
+}
+
+__attribute__ ((visibility("default")))
+void (*__malloc_initialize_hook) (void) = malloc_init;
+
+#else
+
+#endif
diff --git a/src/launchpad.c b/src/launchpad.c
new file mode 100755 (executable)
index 0000000..68c63ce
--- /dev/null
@@ -0,0 +1,839 @@
+/*
+ *  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 "heap_dbg.h"
+
+#include "gl.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 "/usr/lib/da_probe_osp.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 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);
+               }
+       }
+       if (menu_info->hwacc != NULL)
+               setenv("HWACC", menu_info->hwacc, 1);
+}
+
+_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];
+       int ret;
+
+       /* 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(bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) {
+               _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name, menu_info->pkg_type, app_path);
+               if ((ret = __set_access(pkg_name, menu_info->pkg_type, app_path)) < 0) {
+                        _D("fail to set privileges - check your package's credential : %d\n", ret);
+                       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");
+
+       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;
+       const char *str;
+
+       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");
+       _D("lock up test log(no error) : setup argument done");
+
+       /* Temporary log: launch time checking */
+       LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
+
+       str = bundle_get_val(kb, AUL_K_SDK);
+       if ( !(str && strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str))==0) ) {
+               __preload_exec(app_argc, app_argv);
+       }       
+
+       __normal_fork_exec(app_argc, app_argv);
+}
+
+
+/*
+ * 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)
+{
+       bundle_del(kb, AUL_K_PKG_NAME);
+       bundle_del(kb, AUL_K_EXEC);
+       bundle_del(kb, AUL_K_PACKAGETYPE);
+       bundle_del(kb, AUL_K_HWACC);
+
+       /* 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)
+{
+       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_with_noreply(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));
+       menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
+
+       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");
+                       _D("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");
+                       _D("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");
+                       _D("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(DEBUG_LAUNCHPAD_PID);
+       if (fd < 0) {
+               _E("server sock error");
+               return -1;
+       }
+
+       __preload_init(argc, argv);
+
+       __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/sigchild.h b/src/sigchild.h
new file mode 100755 (executable)
index 0000000..bb65707
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ *  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;
+
+       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/simple_util.c b/src/simple_util.c
new file mode 100755 (executable)
index 0000000..d5bbeda
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *  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;
+}
+