tizen 2.3 release tizen_2.3 submit/tizen_2.3/20150202.061353 tizen_2.3_release
authorjk7744.park <jk7744.park@samsung.com>
Sat, 31 Jan 2015 07:29:42 +0000 (16:29 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sat, 31 Jan 2015 07:29:42 +0000 (16:29 +0900)
16 files changed:
CMakeLists.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
launchpad.manifest [new file with mode: 0644]
native/launchpad_native.c [new file with mode: 0644]
native/native_preload.h [new file with mode: 0644]
packaging/launchpad-native-preload-list.txt [new file with mode: 0644]
packaging/launchpad-native.service [new file with mode: 0644]
packaging/launchpad-process-pool-preload-list.txt [new file with mode: 0644]
packaging/launchpad-process-pool.service [new file with mode: 0644]
packaging/launchpad.spec [new file with mode: 0644]
process_pool/launchpad.c [new file with mode: 0644]
process_pool/process_pool.c [new file with mode: 0644]
process_pool/process_pool.h [new file with mode: 0644]
process_pool/process_pool_preload.h [new file with mode: 0644]
process_pool/smack_util.c [new file with mode: 0644]
process_pool/smack_util.h [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..bdaa99e
--- /dev/null
@@ -0,0 +1,89 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET (this_target launchpad)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(${this_target} REQUIRED
+       aul
+       dlog
+       ecore
+       libprivilege-control
+       libsmack
+       deviced
+       elementary
+       libsystemd-daemon
+       )
+
+FOREACH(flag ${${this_target}_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fpic")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -D_FILE_OFFSET_BITS=64")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -I/usr/include/aul/launch -I/usr/include/aul/launchpad")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+SET(CMAKE_SKIP_BUILD_RPATH TRUE)
+
+ADD_DEFINITIONS("-DSHARE_PREFIX=\"/usr/share/aul\"")
+IF(_APPFW_FEATURE_PRIORITY_CHANGE)
+       ADD_DEFINITIONS("-D_APPFW_FEATURE_PRIORITY_CHANGE")
+ENDIF(_APPFW_FEATURE_PRIORITY_CHANGE)
+
+IF(_APPFW_FEATURE_PROCESS_POOL)
+IF(_APPFW_FEATURE_PROCESS_POOL_COMMON)
+       ADD_DEFINITIONS("-D_APPFW_FEATURE_PROCESS_POOL_COMMON")
+ENDIF(_APPFW_FEATURE_PROCESS_POOL_COMMON)
+ADD_DEFINITIONS("-D_APPFW_FEATURE_PROCESS_POOL")
+IF(_APPFW_FEATURE_PROCESS_POOL_HW_RENDERING)
+       ADD_DEFINITIONS("-D_APPFW_FEATURE_PROCESS_POOL_HW_RENDERING")
+ENDIF(_APPFW_FEATURE_PROCESS_POOL_HW_RENDERING)
+
+SET(LAUNCHPAD_PROCESS_POOL "launchpad-process-pool")
+
+SET(${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES
+       process_pool/launchpad.c
+       process_pool/process_pool.c
+       process_pool/smack_util.c
+       )
+ADD_EXECUTABLE(${LAUNCHPAD_PROCESS_POOL} ${${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES})
+
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} aul_mods launchpad_common)
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} aul)
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} "-ldl")
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} ${${this_target}_LDFLAGS})
+
+SET_TARGET_PROPERTIES(${LAUNCHPAD_PROCESS_POOL}
+       PROPERTIES SKIP_BUILD_RPATH TRUE
+       ) # remove rpath option that is automatically generated by cmake.
+
+INSTALL(TARGETS ${LAUNCHPAD_PROCESS_POOL} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/launchpad-process-pool-preload-list.txt DESTINATION share/aul)
+ENDIF(_APPFW_FEATURE_PROCESS_POOL)
+
+IF(_APPFW_FEATURE_NATIVE_LAUNCHPAD)
+ADD_DEFINITIONS("-D_APPFW_FEATURE_NATIVE_LAUNCHPAD")
+
+SET(LAUNCHPAD_NATIVE "launchpad-native")
+
+SET(${LAUNCHPAD_NATIVE}_SOURCE_FILES
+       native/launchpad_native.c
+       )
+ADD_EXECUTABLE(${LAUNCHPAD_NATIVE} ${${LAUNCHPAD_NATIVE}_SOURCE_FILES})
+
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_NATIVE} aul_mods launchpad_common)
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_NATIVE} aul)
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_NATIVE} "-ldl")
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_NATIVE} ${${this_target}_LDFLAGS})
+
+SET_TARGET_PROPERTIES(${LAUNCHPAD_NATIVE}
+       PROPERTIES SKIP_BUILD_RPATH TRUE
+       ) # remove rpath option that is automatically generated by cmake.
+
+INSTALL(TARGETS ${LAUNCHPAD_NATIVE} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/launchpad-native-preload-list.txt DESTINATION share/aul)
+ENDIF(_APPFW_FEATURE_NATIVE_LAUNCHPAD)
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/launchpad.manifest b/launchpad.manifest
new file mode 100644 (file)
index 0000000..4302722
--- /dev/null
@@ -0,0 +1,17 @@
+<manifest>
+       <define>
+               <domain name="launchpad"/>
+               <request>
+                       <smack request="aul::launch" type="x"/>
+                       <smack request="aul::terminate" type="x"/>
+                       <smack request="security-server::api-privilege-by-pid" type="w"/>
+                       <smack request="system::share" type="rwxat"/>
+                       <smack request="sound_server" type="rwx"/>
+                       <smack request="system::homedir" type="rwxat"/>
+                       <smack request="pulseaudio" type="rwxat"/>
+               </request>
+       </define>
+       <request>
+               <domain name="launchpad"/>
+       </request>
+</manifest>
diff --git a/native/launchpad_native.c b/native/launchpad_native.c
new file mode 100644 (file)
index 0000000..f9409e6
--- /dev/null
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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 <sys/resource.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 "util_x.h"
+
+#include "gl.h"
+
+#include <sqlite3.h>
+
+#include "native_preload.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
+
+
+static char *launchpad_cmdline;
+static char *__appid = NULL;
+static int initialized = 0;
+
+_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_ int __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_env(app_info_from_db * menu_info, bundle * kb)
+{
+       const char *str;
+
+       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 (menu_info->hwacc != NULL)
+               setenv("HWACC", menu_info->hwacc, 1);
+       if (menu_info->taskmanage != NULL)
+               setenv("TASKMANAGE", menu_info->taskmanage, 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 PRIVILEGES*/
+       SECURE_LOGD("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");
+
+#ifdef _APPFW_FEATURE_PRIORITY_CHANGE
+       int res = setpriority(PRIO_PROCESS, 0, 0);
+       if (res == -1)
+       {
+               SECURE_LOGE("Setting process (%d) priority to 0 failed, errno: %d (%s)",
+                               getpid(), errno, strerror(errno));
+       }
+#endif
+       if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
+               if (errno == EACCES)
+                       _E("such a file is no executable - %s", argv[0]);
+               else
+                       _E("unknown executable error - %s", argv[0]);
+               return -1;
+       }
+       /* never reach*/
+       return 0;
+}
+
+_static_ void __real_launch(const char *app_path, bundle * kb)
+{
+       int app_argc;
+       char **app_argv;
+       int i;
+
+       app_argv = __create_argc_argv(kb, &app_argc);
+       app_argv[0] = strdup(app_path);
+
+       for (i = 0; i < app_argc; i++) {
+               if( (i%2) == 1)
+                       continue;
+               SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
+       }
+
+       PERF("setup argument done");
+
+       /* Temporary log: launch time checking */
+       SECURE_LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
+
+       __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);
+       bundle_del(kb, AUL_K_TASKMANAGE);
+
+       /* Parse app_path to retrieve default bundle*/
+       if (cmd == APP_START
+               || cmd == APP_START_RES
+               || cmd == APP_START_ASYNC
+#ifdef _APPFW_FEATURE_MULTI_INSTANCE
+               || cmd == APP_START_MULTI_INSTANCE
+#endif
+               || 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;
+                       SECURE_LOGD("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_ int __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");
+                       close(clifd);
+                       return -1;
+               }
+               _E("send fail to client");
+       }
+
+       close(clifd);
+       return 0;
+}
+
+_static_ void __send_result_to_caller(int clifd, int ret)
+{
+       char *cmdline;
+       int wait_count;
+       int cmdline_changed = 0;
+       int cmdline_exist = 0;
+       int r;
+
+       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(100 * 1000);     /* 50ms sleep*/
+               wait_count++;
+       } while (wait_count <= 20);     /* max 100*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");
+
+       if(__real_send(clifd, ret) < 0) {
+               r = kill(ret, SIGKILL);
+               if (r == -1)
+                       _E("send SIGKILL: %s", strerror(errno));
+       }
+
+       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));
+       menu_info->taskmanage = strdup(bundle_get_val(kb, AUL_K_TASKMANAGE));
+
+       if (!_get_app_path(menu_info)) {
+               _free_app_info_from_db(menu_info);
+               return NULL;
+       }
+
+       return menu_info;
+}
+
+static void __release_appid_at_exit(void)
+{
+       if (__appid != NULL) {
+               free(__appid);
+       }
+}
+
+_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);
+       SECURE_LOGD("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");
+
+                       __appid = strdup(pkg_name);
+                       aul_set_preinit_appid(__appid);
+                       atexit(__release_appid_at_exit);
+
+                       if (__prepare_exec(pkg_name, app_path,
+                                          menu_info, kb) < 0) {
+                               SECURE_LOGE("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);
+               }
+               SECURE_LOGD("==> 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(NATIVE_LAUNCHPAD_PID);
+       if (fd < 0) {
+               _E("server sock error");
+               return -1;
+       }
+
+       __preload_init(argc, argv);
+
+       __preload_init_for_native();
+
+       __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;
+
+#ifdef _APPFW_FEATURE_PRIORITY_CHANGE
+       int res = setpriority(PRIO_PROCESS, 0, -12);
+       if (res == -1)
+       {
+               SECURE_LOGE("Setting process (%d) priority to -12 failed, errno: %d (%s)",
+                               getpid(), errno, strerror(errno));
+       }
+#endif
+       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/native/native_preload.h b/native/native_preload.h
new file mode 100644 (file)
index 0000000..965457c
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NATIVE_PRELOAD_H__
+#define __NATIVE_PRELOAD_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#define NATIVE_PRELOAD_FILE SHARE_PREFIX"/launchpad-native-preload-list.txt"
+
+static int g_dlopen_size = 5;
+static int g_dlopen_count = 0;
+static void** g_dlopen_handle_list = NULL;
+
+static inline int __preload_save_dlopen_handle(void *handle)
+{
+    if (!handle) {
+        return 1;
+    }
+    if (g_dlopen_count == g_dlopen_size || !g_dlopen_handle_list) {
+        void** tmp =
+            realloc(g_dlopen_handle_list, 2 * g_dlopen_size * sizeof(void *));
+        if (NULL == tmp) {
+            _E("out of memory\n");
+            dlclose(handle);
+            return 1;
+        }
+        g_dlopen_size *= 2;
+        g_dlopen_handle_list = tmp;
+    }
+    g_dlopen_handle_list[g_dlopen_count++] = handle;
+    return 0;
+}
+
+static inline void __preload_fini_for_native(void)
+{
+    int i = 0;
+    if (!g_dlopen_handle_list) {
+        return;
+    }
+    for (i = 0; i < g_dlopen_count; ++i)
+    {
+        void *handle = g_dlopen_handle_list[i];
+        if (handle) {
+            if (0 != dlclose(handle)) {
+                _E("dlclose failed\n");
+            }
+        }
+    }
+    free(g_dlopen_handle_list);
+    g_dlopen_handle_list = NULL;
+    g_dlopen_size = 5;
+    g_dlopen_count = 0;
+}
+
+static inline void __preload_init_for_native(void)
+{
+    if (atexit(__preload_fini_for_native) != 0) {
+        _E("Cannot register atexit callback. Libraries will not be unloaded");
+    }
+
+       void *handle = NULL;
+       char soname[MAX_LOCAL_BUFSZ] = { 0, };
+       FILE *preload_list = NULL;
+
+       preload_list = fopen(NATIVE_PRELOAD_FILE, "rt");
+       if (preload_list == NULL) {
+               _E("no preload\n");
+               return;
+       }
+
+       while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > 0) {
+        size_t len = strnlen(soname, MAX_LOCAL_BUFSZ);
+        if (len > 0) {
+            soname[len - 1] = '\0';
+        }
+               handle = dlopen((const char *) soname, RTLD_NOW);
+               if (handle == NULL) {
+            _E("dlopen(\"%s\") was failed!", soname);
+            continue;
+        }
+
+        if (__preload_save_dlopen_handle(handle) != 0) {
+            _E("Cannot save handle, no more preloads");
+            break;
+        }
+        _D("preload %s# - handle : %x\n", soname, handle);
+       }
+
+       fclose(preload_list);
+}
+
+#endif //__NATIVE_PRELOAD_H__
diff --git a/packaging/launchpad-native-preload-list.txt b/packaging/launchpad-native-preload-list.txt
new file mode 100644 (file)
index 0000000..bb21d5e
--- /dev/null
@@ -0,0 +1,19 @@
+/usr/lib/osp/libosp-appfw.so.1
+/usr/lib/osp/libosp-uifw.so.1
+/usr/lib/samsung-private/libsamsung-ui.so.1
+/usr/lib/libmirage.so
+/usr/lib/libchart-framework.so
+/usr/lib/samsung-private/libsamsung-media.so.1
+/usr/lib/samsung-private/libsamsung-net.so.1
+/usr/lib/samsung-private/libsamsung-messaging.so.1
+/usr/lib/osp/libosp-media.so.1
+/usr/lib/osp/libosp-messaging.so.1
+/usr/lib/samsung-private/libsamsung-shell.so.1
+/usr/lib/samsung-private/libsamsung-social.so.1
+/usr/lib/osp/libosp-shell.so.1
+/usr/lib/osp/libosp-wifi.so.1
+/usr/lib/osp/libosp-social.so.1
+/usr/lib/osp/libosp-content.so.1
+/usr/lib/samsung-private/libsamsung-content.so.1
+/usr/lib/osp/libosp-image.so.1
+/usr/lib/osp/libosp-net.so.1
diff --git a/packaging/launchpad-native.service b/packaging/launchpad-native.service
new file mode 100644 (file)
index 0000000..2ac3288
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=Start native launchpad daemon
+After=dbus.service vconf-setup.service ac.service
+
+[Service]
+EnvironmentFile=/run/tizen-mobile-env
+ExecStart=/usr/bin/launchpad-native "                                                                                                                                                                                                         "
+TimeoutStopSec=3s
+Restart=always
+RestartSec=0
+
+[Install]
+WantedBy=graphical.target
diff --git a/packaging/launchpad-process-pool-preload-list.txt b/packaging/launchpad-process-pool-preload-list.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/packaging/launchpad-process-pool.service b/packaging/launchpad-process-pool.service
new file mode 100644 (file)
index 0000000..bccc8cb
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=Start process-pool launchpad daemon
+After=dbus.service vconf-setup.service ac.service
+
+[Service]
+EnvironmentFile=/run/tizen-mobile-env
+ExecStart=/usr/bin/launchpad-process-pool "                                                                                                                                                                                                         "
+TimeoutStopSec=3s
+Restart=always
+RestartSec=0
+
+[Install]
+WantedBy=graphical.target
diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec
new file mode 100644 (file)
index 0000000..3f32ffc
--- /dev/null
@@ -0,0 +1,129 @@
+Name:       launchpad
+Summary:    Launchpad for launching applications
+Version:    0.0.20
+Release:    1
+Group:      Application Framework/Daemons
+License:    Apache License, Version 2.0
+Source0:    %{name}-%{version}.tar.gz
+Source101:  launchpad-process-pool.service
+Source102:  launchpad-native.service
+
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(dbus-glib-1)
+BuildRequires:  pkgconfig(sqlite3)
+BuildRequires:  pkgconfig(ecore)
+BuildRequires:  pkgconfig(bundle)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(ail)
+BuildRequires:  pkgconfig(libprivilege-control)
+BuildRequires:  pkgconfig(libsmack)
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(deviced)
+BuildRequires:  pkgconfig(libsystemd-daemon)
+BuildRequires:  pkgconfig(elementary)
+BuildRequires:  pkgconfig(eina)
+BuildRequires:  aul-devel
+
+Requires: aul
+Requires(post): /sbin/ldconfig
+Requires(post): /usr/bin/systemctl
+Requires(postun): /sbin/ldconfig
+Requires(postun): /usr/bin/systemctl
+Requires(preun): /usr/bin/systemctl
+
+%define feature_appfw_process_pool 1
+
+%if "%{?tizen_profile_name}" == "wearable"
+%define appfw_feature_process_pool_common 1
+%define appfw_feature_hw_rendering 0
+%elseif "%{?tizen_profile_name}" == "mobile"
+%define appfw_feature_process_pool_common 0
+%define appfw_feature_hw_rendering 1
+%endif
+%define appfw_feature_priority_change 1
+%define appfw_feature_native_launchpad 0
+
+%description
+Launchpad for launching applications
+
+%package devel
+Summary:    Launchpad for launching applications (devel)
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+Launchpad for launching applications (devel)
+
+%prep
+%setup -q
+
+%build
+%if 0%{?sec_build_binary_debug_enable}
+export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
+export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
+%endif
+%if 0%{?feature_appfw_process_pool}
+_APPFW_FEATURE_PROCESS_POOL=ON
+ %if 0%{?appfw_feature_process_pool_common}
+ _APPFW_FEATURE_PROCESS_POOL_COMMON=ON
+ %else
+  %if 0%{?appfw_feature_hw_rendering}
+  _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING=ON
+  %endif
+ %endif
+%endif
+%if 0%{?appfw_feature_priority_change}
+_APPFW_FEATURE_PRIORITY_CHANGE=ON
+%endif
+%if 0%{?appfw_feature_native_launchpad}
+_APPFW_FEATURE_NATIVE_LAUNCHPAD=ON
+%endif
+
+cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} \
+       -D_APPFW_FEATURE_PROCESS_POOL:BOOL=${_APPFW_FEATURE_PROCESS_POOL} \
+       -D_APPFW_FEATURE_PROCESS_POOL_COMMON:BOOL=${_APPFW_FEATURE_PROCESS_POOL_COMMON} \
+       -D_APPFW_FEATURE_PROCESS_POOL_HW_RENDERING:BOOL=${_APPFW_FEATURE_PROCESS_POOL_HW_RENDERING} \
+       -D_APPFW_FEATURE_PRIORITY_CHANGE:BOOL=${_APPFW_FEATURE_PRIORITY_CHANGE} \
+       -D_APPFW_FEATURE_NATIVE_LAUNCHPAD:BOOL=${_APPFW_FEATURE_NATIVE_LAUNCHPAD}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%if 0%{?feature_appfw_process_pool} || 0%{?appfw_feature_native_launchpad}
+%make_install
+%endif
+
+%if 0%{?feature_appfw_process_pool}
+mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants
+install -m0644 %SOURCE101 %{buildroot}%{_libdir}/systemd/system/launchpad-process-pool.service
+ln -s ../launchpad-process-pool.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/launchpad-process-pool.service
+%endif
+
+%if 0%{?appfw_feature_native_launchpad}
+mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants
+install -m0644 %SOURCE102 %{buildroot}%{_libdir}/systemd/system/launchpad-native.service
+ln -s ../launchpad-native.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/launchpad-native.service
+%endif
+
+mkdir -p %{buildroot}/usr/share/license
+cp %{_builddir}/%{name}-%{version}/LICENSE  %{buildroot}/usr/share/license/%{name}
+
+%post
+
+%files
+%manifest launchpad.manifest
+%{_prefix}/share/license/%{name}
+%if 0%{?feature_appfw_process_pool}
+%{_bindir}/launchpad-process-pool
+%{_prefix}/share/aul/launchpad-process-pool-preload-list.txt
+%{_libdir}/systemd/system/launchpad-process-pool.service
+%{_libdir}/systemd/system/graphical.target.wants/launchpad-process-pool.service
+%endif
+%if 0%{?appfw_feature_native_launchpad}
+%{_bindir}/launchpad-native
+%{_prefix}/share/aul/launchpad-native-preload-list.txt
+%{_libdir}/systemd/system/launchpad-native.service
+%{_libdir}/systemd/system/graphical.target.wants/launchpad-native.service
+%endif
diff --git a/process_pool/launchpad.c b/process_pool/launchpad.c
new file mode 100644 (file)
index 0000000..b9f550c
--- /dev/null
@@ -0,0 +1,1375 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <poll.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#define __USE_GNU
+#include <sys/socket.h>
+
+#include <sqlite3.h>
+
+#include <aul.h>
+#include <Elementary.h>
+#include <Ecore.h>
+
+#include <config.h> //should be included first
+
+//including aul/launch
+#include <access_control.h>
+#include <app_sock.h>
+#include <aul_util.h>
+#include <menu_db_util.h>
+#include <perf.h>
+#include <simple_util.h>
+
+//including aul/launchpad
+#include <gl.h>
+#include <heap_dbg.h>
+#include <preexec.h>
+#include <preload.h>
+#include <sigchild.h>
+#include <util_x.h>
+
+#include "process_pool.h"
+#include "process_pool_preload.h"
+
+#include "smack_util.h"
+
+#define _static_ static inline
+#define SQLITE_FLUSH_MAX       (1048576)       /* (1024*1024) */
+#define AUL_POLL_CNT           15
+#define AUL_PR_NAME                    16
+
+#define EXEC_CANDIDATE_EXPIRED 5
+#define DIFF(a,b) (((a)>(b))?(a)-(b):(b)-(a))
+#define LOWEST_PRIO 20
+#define CANDIDATE_NONE 0
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+ #ifndef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+ #define MAX_LAUNCHPAD_TYPE_NUM 1
+ #else
+ #define MAX_LAUNCHPAD_TYPE_NUM 2
+ #endif
+#else //_APPFW_FEATURE_PROCESS_POOL_COMMON
+#define MAX_LAUNCHPAD_TYPE_NUM 1
+#endif //_APPFW_FEATURE_PROCESS_POOL_COMMON
+
+typedef struct
+{
+       int pid;
+       int send_fd;
+       int last_exec_time;
+} candidate;
+
+static char *launchpad_cmdline;
+static char *__appid = NULL;
+static int initialized = 0;
+static candidate __candidate[MAX_LAUNCHPAD_TYPE_NUM] =
+{
+       { CANDIDATE_NONE, -1, 0 },
+       { CANDIDATE_NONE, -1, 0 }
+};
+const char* const HOME = "HOME";
+const char* const APP_HOME_PATH = "/opt/home/app";
+const char* const ROOT_HOME_PATH = "/opt/home/root";
+
+_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_ int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt);
+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_ int __real_send(int clifd, int ret);
+_static_ void __send_result_to_caller(int clifd, int ret);
+_static_ void __prepare_candidate_process(int type, int launchpad_fd, int pool_fd, int client_fd);
+_static_ void __launchpad_main_loop(int launchpad_fd, int *pool_fd);
+_static_ int __launchpad_pre_init(int argc, char **argv);
+_static_ int __launchpad_post_init();
+
+static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
+                                                       const char *pkgname, bundle *kb);
+
+_static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
+{
+       const char *str;
+
+       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 (menu_info->hwacc != NULL)
+               setenv("HWACC", menu_info->hwacc, 1);
+       if (menu_info->taskmanage != NULL)
+               setenv("TASKMANAGE", menu_info->taskmanage, 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 PRIVILEGES*/
+       SECURE_LOGD("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");
+
+#ifdef _APPFW_FEATURE_PRIORITY_CHANGE
+       int res = setpriority(PRIO_PROCESS, 0, 0);
+       if (res == -1)
+       {
+               SECURE_LOGE("Setting process (%d) priority to 0 failed, errno: %d (%s)",
+                               getpid(), errno, strerror(errno));
+       }
+#endif
+       if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
+               if (errno == EACCES)
+                       _E("such a file is no executable - %s", argv[0]);
+               else
+                       _E("unknown executable error - %s", argv[0]);
+               return -1;
+       }
+       /* never reach*/
+       return 0;
+}
+
+_static_ void __real_launch(const char *app_path, bundle * kb)
+{
+       int app_argc;
+       char **app_argv;
+       int i;
+
+       app_argv = __create_argc_argv(kb, &app_argc);
+       app_argv[0] = strdup(app_path);
+
+       for (i = 0; i < app_argc; i++) {
+               if( (i%2) == 1)
+                       continue;
+               SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
+       }
+
+       PERF("setup argument done");
+
+       /* Temporary log: launch time checking */
+       LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
+
+       __preload_exec(app_argc, app_argv);
+
+       __normal_fork_exec(app_argc, app_argv);
+}
+
+_static_ int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt)
+{
+       return __send_pkt_raw_data(candidate_fd, pkt);
+}
+
+/*
+ * 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);
+       bundle_del(kb, AUL_K_TASKMANAGE);
+
+       /* 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;
+                       SECURE_LOGD("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_ int __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");
+                       close(clifd);
+                       return -1;
+               }
+               _E("send fail to client");
+       }
+
+       close(clifd);
+       return 0;
+}
+
+_static_ void __send_result_to_caller(int clifd, int ret)
+{
+       char *cmdline;
+       int wait_count;
+       int cmdline_changed = 0;
+       int cmdline_exist = 0;
+       int r;
+
+       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(100 * 1000);     /* 50ms sleep*/
+               wait_count++;
+       } while (wait_count <= 20);     /* max 100*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");
+
+       if(__real_send(clifd, ret) < 0) {
+               r = kill(ret, SIGKILL);
+               if (r == -1)
+                       _E("send SIGKILL: %s", strerror(errno));
+       }
+
+       return;
+}
+
+_static_ int __candidate_process_prepare_exec(const char *pkg_name,
+                                                       const char *app_path, app_info_from_db *menu_info,
+                                                       bundle *kb, int type)
+{
+       const char *file_name = NULL;
+       char process_name[AUL_PR_NAME] = { 0, };
+       int ret = 0;
+
+       if (set_app_smack_label(app_path, type) != 0)
+       {
+               _E("set_app_smack_label() failed");
+       }
+
+       /* SET PRIVILEGES*/
+       SECURE_LOGD("[candidata] 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;
+       }
+
+       //XXX: Check CAP_MAC_ADMIN
+#if 0
+       /* SET INHERIT BIT FOR CAP_MAC_ADMIN TO WHOLE THREAD */
+       EXECUTE_ON_WHOLE_THREAD(__set_inherit_bit_for_CAP_MAC_ADMIN, SIGUSR1);
+#endif
+
+       /* 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 bundle *_s_bundle = NULL;
+static void __at_exit_to_release_bundle()
+{
+       if (_s_bundle) {
+               bundle_free(_s_bundle);
+               _s_bundle = NULL;
+       }
+}
+
+static void __release_appid_at_exit(void)
+{
+       if (__appid != NULL) {
+               free(__appid);
+       }
+}
+
+_static_ void __candidate_process_launchpad_main_loop(app_pkt_t* pkt, char* out_app_path, int* out_argc, char ***out_argv)
+{
+       bundle *kb = NULL;
+       app_info_from_db *menu_info = NULL;
+
+       const char *pkg_name = NULL;
+       const char *app_path = NULL;
+       const char *launchpad_type = NULL;
+       int type = 0;
+
+       kb = bundle_decode(pkt->data, pkt->len);
+       if (!kb) {
+               _E("bundle decode error");
+               exit(-1);
+       }
+
+       if (_s_bundle != NULL) {
+               bundle_free(_s_bundle);
+       }
+       _s_bundle = kb;
+       atexit(__at_exit_to_release_bundle);
+
+       pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
+       menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
+       if (menu_info == NULL) {
+               _D("such pkg no found");
+               exit(-1);
+       }
+
+       launchpad_type = bundle_get_val(kb, AUL_K_LAUNCHPAD_TYPE);
+       if (launchpad_type == NULL)
+       {
+               _E("Invalid launchpad type");
+               exit(-1);
+       }
+       type = atoi(launchpad_type);
+       SECURE_LOGD("pkg name : %s, launchpad type: %d", pkg_name, type);
+
+       app_path = _get_app_path(menu_info);
+       if (app_path == NULL) {
+               _E("app_path is NULL");
+               exit(-1);
+       }
+
+       if (app_path[0] != '/') {
+               _E("app_path is not absolute path");
+               exit(-1);
+       }
+
+       __modify_bundle(kb, /*cr.pid - unused parameter*/ 0, menu_info, pkt->cmd);
+       pkg_name = _get_pkgname(menu_info);
+       SECURE_LOGD("pkg name : %s", pkg_name);
+
+       __appid = strdup(pkg_name);
+       aul_set_preinit_appid(__appid);
+       atexit(__release_appid_at_exit);
+
+       __candidate_process_prepare_exec(pkg_name, app_path, menu_info, kb, type);
+
+       if (out_app_path != NULL && out_argc != NULL && out_argv != NULL)
+       {
+               int i = 0;
+
+               memset(out_app_path, '\0', strlen(out_app_path));
+               sprintf(out_app_path, "%s", app_path);
+
+               *out_argv = __create_argc_argv(kb, out_argc);
+               (*out_argv)[0] = out_app_path;
+
+               for (i = 0; i < *out_argc; i++)
+               {
+                       SECURE_LOGD("input argument %d : %s##", i, (*out_argv)[i]);
+               }
+       }
+       else
+       {
+               exit(-1);
+       }
+
+       if (menu_info != NULL) {
+               _free_app_info_from_db(menu_info);
+       }
+}
+
+static Eina_Bool __candidate_proces_fd_handler(void* data, Ecore_Fd_Handler *handler)
+{
+       int fd = ecore_main_fd_handler_fd_get(handler);
+
+       if (fd == -1)
+       {
+               _D("[candidate] ECORE_FD_GET");
+               exit(-1);
+       }
+
+       if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
+       {
+               _D("[candidate] ECORE_FD_ERROR");
+               close(fd);
+               exit(-1);
+       }
+
+       if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
+       {
+               _D("[candidate] ECORE_FD_READ");
+               {
+                       app_pkt_t* pkt = (app_pkt_t*) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
+                       memset(pkt, 0, AUL_SOCK_MAXBUFF);
+
+                       int recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
+                       close(fd);
+                       if (recv_ret == -1)
+                       {
+                               _D("[condidate] recv error!");
+                               free(pkt);
+                               exit(-1);
+                       }
+                       _D("[candidate] recv_ret: %d, pkt->len: %d", recv_ret, pkt->len);
+
+                       ecore_main_fd_handler_del(handler);
+                       __candidate_process_launchpad_main_loop(pkt, g_argv[0], &g_argc, &g_argv);
+                       SECURE_LOGD("[candidate] real app argv[0]: %s, real app argc: %d", g_argv[0], g_argc);
+                       free(pkt);
+               }
+               ecore_main_loop_quit();
+               _D("[candidate] ecore main loop quit");
+       }
+
+       return ECORE_CALLBACK_CANCEL;
+}
+
+_static_ void __prepare_candidate_process(int type, int launchpad_fd, int pool_fd, int client_fd)
+{
+       int pid;
+
+       if (type == 1)
+       {
+               __candidate[TYPE1].last_exec_time = time(NULL);
+       }
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+#ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+       else if (type == 2)
+       {
+               __candidate[TYPE2].last_exec_time = time(NULL);
+       }
+#endif
+#endif
+
+       pid = fork();
+
+       if (pid == 0) // child
+       {
+               int res = setpriority(PRIO_PROCESS, 0, LOWEST_PRIO);
+               if (res == -1)
+               {
+                       SECURE_LOGE("Setting process (%d) priority to %d failed, errno: %d (%s)",
+                                       getpid(), LOWEST_PRIO, errno, strerror(errno));
+               }
+               _D("[candidate] Another candidate process was forked.");
+
+               //temp - this requires some optimization.
+               sleep(1);
+               _D("sleeping 1 sec...");
+
+               /* 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();
+
+               if (launchpad_fd != -1)
+               {
+                       close(launchpad_fd);
+               }
+               if (pool_fd != -1)
+               {
+                       close(pool_fd);
+               }
+               if (client_fd != -1)
+               {
+                       close(client_fd);
+               }
+
+               __signal_unset_sigchld();
+               __signal_fini();
+
+#if 0
+               if (set_SIGUSR1_handler() != 0)
+               {
+                       _E("Setting signal hanlder failed.");
+                       exit(-1);
+               }
+#endif
+
+               /* SET PR_SET_KEEPCAPS */
+               if (prctl(PR_SET_KEEPCAPS, 1) < 0)
+               {
+                       _E("prctl(PR_SET_KEEPCAPS) failed.");
+               }
+
+               /* SET DUMPABLE - for coredump*/
+               prctl(PR_SET_DUMPABLE, 1);
+
+               {
+                       int client_fd = __connect_to_launchpad(type);
+                       if (client_fd == -1)
+                       {
+                               _D("Connecting to candidate process was failed.");
+                               exit(-1);
+                       }
+
+                       // Temporarily change HOME path to app
+                       // This change is needed for getting elementary profile
+                       // /opt/home/app/.elementary/config/mobile/base.cfg
+                       setenv(HOME, APP_HOME_PATH, 1);
+                       _D("[candidate] elm_init()");
+                       elm_init(g_argc, g_argv);
+                       setenv(HOME, ROOT_HOME_PATH, 1);
+
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+ #ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+                       if (type == 2)
+                       {
+                               elm_config_preferred_engine_set("opengl_x11");
+                       }
+ #endif
+                       Evas_Object* win = elm_win_add(NULL, "package_name", ELM_WIN_BASIC);
+                       aul_set_preinit_window(win);
+
+                       Evas_Object* bg = elm_bg_add(win);
+                       evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                       elm_win_resize_object_add(win, bg);
+
+                       aul_set_preinit_background(bg);
+
+                       Evas_Object* conform = elm_conformant_add(win);
+                       aul_set_preinit_conformant(conform);
+#else //_APPFW_FEATURE_PROCESS_POOL_COMMON
+                       Eina_Bool is_exist = edje_file_group_exists("/usr/share/elementary/themes/tizen-2.3-wearable-HVGA.edj", "*");
+                       if(!is_exist)
+                               _D("edje_file_group_exists return false");
+#endif //_APPFW_FEATURE_PROCESS_POOL_COMMON
+
+                       Ecore_Fd_Handler* fd_handler = ecore_main_fd_handler_add(client_fd,
+                                                                                  (Ecore_Fd_Handler_Flags)(ECORE_FD_READ|ECORE_FD_ERROR),
+                                                                                  __candidate_proces_fd_handler, NULL, NULL, NULL);
+                       if (fd_handler == NULL)
+                       {
+                               _D("fd_handler is NULL");
+                               exit(-1);
+                       }
+
+                       res = setpriority(PRIO_PGRP, 0, 0);
+                       if (res == -1)
+                       {
+                               SECURE_LOGE("Setting process (%d) priority to 0 failed, errno: %d (%s)",
+                                               getpid(), errno, strerror(errno));
+                       }
+
+                       _D("[candidate] ecore main loop begin");
+                       ecore_main_loop_begin();
+
+                       void *handle = NULL;
+                       int (*dl_main) (int, char **);
+
+                       SECURE_LOGD("[candidate] Launch real application (%s)", g_argv[0]);
+                       handle = dlopen(g_argv[0], RTLD_LAZY | RTLD_GLOBAL);
+                       if (handle == NULL)
+                       {
+                               _E("dlopen failed (%s).", dlerror());
+                               exit(-1);
+                       }
+                       dlerror();
+
+                       dl_main = dlsym(handle, "main");
+                       if (dl_main != NULL)
+                       {
+                               dl_main(g_argc, g_argv);
+                       }
+                       else
+                       {
+                               _E("dlsym not founded. bad preloaded app - check fpie pie");
+                       }
+
+                       exit(0);
+               }
+       }
+}
+
+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));
+       menu_info->taskmanage = strdup(bundle_get_val(kb, AUL_K_TASKMANAGE));
+
+       if (!_get_app_path(menu_info)) {
+               _free_app_info_from_db(menu_info);
+               return NULL;
+       }
+
+       return menu_info;
+}
+
+_static_ void __launchpad_main_loop(int launchpad_fd, int *pool_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;
+       const char *launchpad_type = NULL;
+       int pid = -1;
+       int clifd = -1;
+       struct ucred cr;
+       int is_real_launch = 0;
+       char sock_path[UNIX_PATH_MAX] = {0,};
+       int type = -1;
+
+       pkt = __app_recv_raw(launchpad_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);
+       SECURE_LOGD("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;
+       }
+
+       launchpad_type = bundle_get_val(kb, AUL_K_LAUNCHPAD_TYPE);
+       if (launchpad_type == NULL)
+       {
+               _E("[launchpad] invalid launchpad type");
+               goto end;
+       }
+       type = atoi(launchpad_type);
+       _D("[launchpad] launchpad type: %d", type);
+
+       __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
+       pkg_name = _get_pkgname(menu_info);
+
+       PERF("get package information & modify bundle done");
+
+       if ((type == 1 && __candidate[TYPE1].pid != CANDIDATE_NONE)
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+ #ifndef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+               )
+ #else
+               || (type == 2 && __candidate[TYPE2].pid != CANDIDATE_NONE))
+ #endif
+#else //_APPFW_FEATURE_PROCESS_POOL_COMMON
+               )
+#endif //_APPFW_FEATURE_PROCESS_POOL_COMMON
+       {
+               int i = type - 1;
+               snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, __candidate[i].pid);
+               unlink(sock_path);
+
+               __candidate_process_real_launch(__candidate[i].send_fd, pkt);
+               _D("Request real launch to candidate_process.");
+
+               pid = __candidate[i].pid;
+               is_real_launch = 1;
+               close(__candidate[i].send_fd);
+
+               __candidate[i].pid = CANDIDATE_NONE;
+               __candidate[i].send_fd = -1;
+
+               /* Temporary log: launch time checking */
+               //LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
+
+               __prepare_candidate_process(type, launchpad_fd, pool_fd[type - 1], clifd);
+
+               SECURE_LOGD("Prepare candidate process, pid: %d, bin path: %s\n", pid, app_path);
+       }
+       else
+       {
+               // legacy approach
+               pid = fork();
+
+               if (pid == 0)
+               {
+                       PERF("fork done");
+                       _E("lock up test log(no error) : fork done");
+
+                       close(clifd);
+                       close(launchpad_fd);
+                       __signal_unset_sigchld();
+                       __signal_fini();
+
+                       snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid());
+                       unlink(sock_path);
+
+                       PERF("prepare exec - first done");
+                       _E("lock up test log(no error) : prepare exec - first done");
+
+                       if (__prepare_exec(pkg_name, app_path, menu_info, kb) < 0)
+                       {
+                               SECURE_LOGE("preparing work fail to launch - "
+                                  "can not launch %s\n", pkg_name);
+                               exit(-1);
+                       }
+
+                       PERF("prepare exec - second done");
+                       _E("lock up test log(no error) : prepare exec - second done");
+
+                       __real_launch(app_path, kb);
+
+                       exit(-1);
+               }
+               _D("==> real launch pid : %d %s\n", pid, app_path);
+               is_real_launch = 1;
+       }
+end:
+       __send_result_to_caller(clifd, pid);
+
+       if (pid > 0)
+       {
+               if (is_real_launch)
+               {
+                       /*TODO: retry*/
+                       __signal_block_sigchld();
+                       __send_app_launch_signal(pid);
+                       __signal_unblock_sigchld();
+               }
+       }
+
+       if (menu_info != NULL)
+       {
+               _free_app_info_from_db(menu_info);
+       }
+
+       if (kb != NULL)
+       {
+               bundle_free(kb);
+       }
+       if (pkt != NULL)
+       {
+               free(pkt);
+       }
+
+       /* Active Flusing for Daemon */
+       if (initialized > AUL_POLL_CNT)
+       {
+               sqlite3_release_memory(SQLITE_FLUSH_MAX);
+               malloc_trim(0);
+               initialized = 1;
+       }
+}
+
+_static_ int __launchpad_pre_init(int argc, char **argv)
+{
+       int fd;
+
+       /* signal init*/
+       __signal_init();
+
+       /* get my(launchpad) command line*/
+       launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
+       if (launchpad_cmdline == NULL) {
+               _E("launchpad cmdline fail to get");
+               return -1;
+       }
+       _D("launchpad cmdline: %s", launchpad_cmdline);
+
+       /* create launchpad sock */
+       fd = __create_server_sock(PROCESS_POOL_LAUNCHPAD_PID);
+       if (fd < 0)
+       {
+               _E("server sock error");
+               return -1;
+       }
+
+       __preload_init(argc, argv);
+
+       __preload_init_for_process_pool();
+
+//     __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)
+{
+       enum {
+               LAUNCH_PAD = 0,
+               POOL_TYPE1,
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+#ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+               POOL_TYPE2,
+#endif
+#endif
+               CANDIDATE_TYPE1,
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+#ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+               CANDIDATE_TYPE2,
+#endif
+#endif
+               POLLFD_MAX
+       };
+       int launchpad_fd = -1;
+       int pool_fd[MAX_LAUNCHPAD_TYPE_NUM] =
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+ #ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+       { -1, -1 };
+ #else
+       { -1 };
+ #endif
+#else //_APPFW_FEATURE_PROCESS_POOL_COMMON
+       { -1 };
+#endif //_APPFW_FEATURE_PROCESS_POOL_COMMON
+       struct pollfd pfds[POLLFD_MAX];
+       int i;
+
+       memset(pfds, 0x00, sizeof(pfds));
+
+       /* init without concerning X & EFL*/
+       launchpad_fd = __launchpad_pre_init(argc, argv);
+       if (launchpad_fd < 0)
+       {
+               _E("launchpad pre init failed");
+               exit(-1);
+       }
+       pfds[LAUNCH_PAD].fd      = launchpad_fd;
+       pfds[LAUNCH_PAD].events  = POLLIN;
+       pfds[LAUNCH_PAD].revents = 0;
+
+       for (i = 0; i < MAX_LAUNCHPAD_TYPE_NUM; ++i)
+       {
+               pool_fd[i] = __listen_candidate_process(i + 1);
+               if (pool_fd[i] == -1)
+               {
+                       _E("[launchpad] Listening the socket to the type%d candidate process failed.", i + 1);
+                       goto error;
+               }
+               pfds[POOL_TYPE1 + i].fd          = pool_fd[i];
+               pfds[POOL_TYPE1 + i].events  = POLLIN;
+               pfds[POOL_TYPE1 + i].revents = 0;
+       }
+
+#ifdef _APPFW_FEATURE_PRIORITY_CHANGE
+       int res = setpriority(PRIO_PROCESS, 0, -12);
+       if (res == -1)
+       {
+               SECURE_LOGE("Setting process (%d) priority to -12 failed, errno: %d (%s)",
+                               getpid(), errno, strerror(errno));
+       }
+#endif
+       while (1)
+       {
+               for (i = 0; i < MAX_LAUNCHPAD_TYPE_NUM; ++i)
+               {
+                       if (__candidate[i].pid == CANDIDATE_NONE)
+                       {
+                               pfds[CANDIDATE_TYPE1 + i].fd      = -1;
+                               pfds[CANDIDATE_TYPE1 + i].events  = 0;
+                               pfds[CANDIDATE_TYPE1 + i].revents = 0;
+
+                               if (DIFF(__candidate[i].last_exec_time, time(NULL)) > EXEC_CANDIDATE_EXPIRED)
+                               {
+                                       __prepare_candidate_process(i + 1, launchpad_fd, pool_fd[i], -1);
+                               }
+                       }
+               }
+
+               if (poll(pfds, POLLFD_MAX, -1) < 0)
+                       continue;
+
+               _D("pfds[LAUNCH_PAD].revent  : 0x%x", pfds[LAUNCH_PAD].revents) ;
+               _D("pfds[POOL_TYPE1].revents : 0x%x", pfds[POOL_TYPE1].revents) ;
+               _D("pfds[CANDIDATE_TYPE1].revents : 0x%x", pfds[CANDIDATE_TYPE1].revents) ;
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+#ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+               _D("pfds[POOL_TYPE2].revents : 0x%x", pfds[POOL_TYPE2].revents) ;
+               _D("pfds[CANDIDATE_TYPE2].revents : 0x%x", pfds[CANDIDATE_TYPE2].revents);
+#endif
+#endif
+               /* init with concerning X & EFL (because of booting
+               * sequence problem)*/
+               if (__launchpad_post_init() < 0)
+               {
+                       _E("launcpad post init failed");
+                       goto error;
+               }
+
+               if ((pfds[LAUNCH_PAD].revents & POLLIN) != 0)
+               {
+                       _D("pfds[LAUNCH_PAD].revents & POLLIN");
+                       __launchpad_main_loop(pfds[LAUNCH_PAD].fd, pool_fd);
+               }
+
+               for (i = 0; i < MAX_LAUNCHPAD_TYPE_NUM; ++i)
+               {
+                       if ((pfds[POOL_TYPE1 + i].revents & POLLIN) != 0)
+                       {
+                               int server_fd, client_fd;
+                               int client_pid;
+
+                               server_fd = pfds[POOL_TYPE1 + i].fd;
+
+                               _D("pfds[POOL_TYPE%d].revents & POLLIN", i + 1);
+
+                               if (__candidate[i].pid == CANDIDATE_NONE)
+                               {
+                                       __accept_candidate_process(server_fd, &client_fd, &client_pid);
+
+                                       __candidate[i].pid = client_pid;
+                                       __candidate[i].send_fd = client_fd;
+
+                                       pfds[CANDIDATE_TYPE1 + i].fd      = client_fd;
+                                       pfds[CANDIDATE_TYPE1 + i].events  = POLLIN | POLLHUP;
+                                       pfds[CANDIDATE_TYPE1 + i].revents = 0;
+
+                                       SECURE_LOGD("Type%d candidate process was connected, pid: %d", i + 1, __candidate[i].pid);
+                               }
+                               else
+                               {
+                                       __refuse_candidate_process(server_fd);
+                                       _E("Refused candidate process connection");
+                               }
+                       }
+
+                       if ((pfds[CANDIDATE_TYPE1 + i].revents & (POLLHUP | POLLNVAL)) != 0)
+                       {
+                               SECURE_LOGD("pfds[CANDIDATE_TYPE%d].revents & (POLLHUP|POLLNVAL), pid: %d", i + 1, __candidate[i].pid);
+
+                               if (pfds[CANDIDATE_TYPE1 + i].fd > -1)
+                               {
+                                       close(pfds[CANDIDATE_TYPE1 + i].fd);
+                               }
+
+                               __candidate[i].pid = CANDIDATE_NONE;
+                               __candidate[i].send_fd = -1;
+
+                               pfds[CANDIDATE_TYPE1 + i].fd      = -1;
+                               pfds[CANDIDATE_TYPE1 + i].events  = 0;
+                               pfds[CANDIDATE_TYPE1 + i].revents = 0;
+                       }
+               }
+       }
+
+       return 0;
+
+error:
+       if (launchpad_fd != -1)
+       {
+               close(launchpad_fd);
+       }
+
+       for (i = 0; i < MAX_LAUNCHPAD_TYPE_NUM; ++i)
+       {
+               if (pool_fd[i] != -1)
+               {
+                       close(pool_fd[i]);
+               }
+               if (__candidate[i].send_fd != -1)
+               {
+                       close(__candidate[i].send_fd);
+               }
+       }
+
+       return -1;
+}
diff --git a/process_pool/process_pool.c b/process_pool/process_pool.c
new file mode 100644 (file)
index 0000000..7e62150
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <linux/un.h>
+#include <errno.h>
+#include <systemd/sd-daemon.h>
+
+#include <simple_util.h>
+
+#include "process_pool.h"
+
+#define TMP_PATH "/tmp"
+#define LAUNCHPAD_TYPE1 ".launchpad-type1"
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+ #ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+ #define LAUNCHPAD_TYPE2 ".launchpad-type2"
+ #endif
+#endif //_APPFW_FEATURE_PROCESS_POOL_COMMON
+#define MAX_PENDING_CONNECTIONS 10
+#define CONNECT_RETRY_TIME 100 * 1000
+#define CONNECT_RETRY_COUNT 3
+
+int __listen_candidate_process(int type)
+{
+       struct sockaddr_un addr;
+       int fd = -1;
+       int listen_fds = 0;
+       int i;
+
+       _D("[launchpad] enter, type: %d", type);
+
+       memset(&addr, 0x00, sizeof(struct sockaddr_un));
+       addr.sun_family = AF_UNIX;
+       if (type == 1)
+       {
+               snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%s", TMP_PATH, LAUNCHPAD_TYPE1);
+       }
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+#ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+       else if (type == 2)
+       {
+               snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%s", TMP_PATH, LAUNCHPAD_TYPE2);
+       }
+#endif
+#endif
+       listen_fds = sd_listen_fds(0);
+       if (listen_fds < 0)
+       {
+               _E("Invalid systemd environment");
+               return -1;
+       }
+       else if (listen_fds > 0)
+       {
+               for (i = 0; i < listen_fds; i++)
+               {
+                       fd = SD_LISTEN_FDS_START + i;
+                       if (sd_is_socket_unix(fd, SOCK_STREAM, 1, addr.sun_path, 0))
+                               return fd;
+               }
+               _E("Socket not found: %s", addr.sun_path);
+               return -1;
+       }
+
+       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+       if (fd < 0)
+       {
+               _E("Socket error");
+               goto error;
+       }
+
+       unlink(addr.sun_path);
+
+       _D("bind to %s", addr.sun_path);
+       if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+       {
+               _E("bind error");
+               goto error;
+       }
+
+       _D("chmod %s", addr.sun_path);
+       if (chmod(addr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0)
+       {
+               _E("chmod error");
+               goto error;
+       }
+
+       _D("listen to %s", addr.sun_path);
+       if (listen(fd, MAX_PENDING_CONNECTIONS) == -1)
+       {
+               _E("listen error");
+               goto error;
+       }
+
+       SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
+       return fd;
+
+error:
+       if (fd != -1)
+       {
+               close(fd);
+       }
+
+       return -1;
+}
+
+int __connect_to_launchpad(int type)
+{
+       struct sockaddr_un addr;
+       int fd = -1;
+       int retry = CONNECT_RETRY_COUNT;
+       int send_ret = -1;
+       int client_pid = getpid();
+
+       _D("[launchpad] enter, type: %d", type);
+
+       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+       if (fd < 0)
+       {
+               _E("socket error");
+               goto error;
+       }
+
+       memset(&addr, 0x00, sizeof(struct sockaddr_un));
+       addr.sun_family = AF_UNIX;
+       if (type == 1)
+       {
+               snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%s", TMP_PATH, LAUNCHPAD_TYPE1);
+       }
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+#ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+       else if (type == 2)
+       {
+               snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%s", TMP_PATH, LAUNCHPAD_TYPE2);
+       }
+#endif
+#endif
+       _D("connect to %s", addr.sun_path);
+       while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+       {
+               if (errno != ETIMEDOUT || retry <= 0)
+               {
+                       _E("connect error : %d", errno);
+                       goto error;
+               }
+
+               usleep(CONNECT_RETRY_TIME);
+               --retry;
+               _D("re-connect to %s (%d)", addr.sun_path, retry);
+       }
+
+       send_ret = send(fd, &client_pid, sizeof(client_pid), 0);
+       _D("send(%d) : %d", client_pid, send_ret);
+
+       if (send_ret == -1)
+       {
+               _E("send error");
+               goto error;
+       }
+
+       SECURE_LOGD("[launchpad] done, connect fd: %d", fd);
+       return fd;
+
+error:
+       if (fd != -1)
+       {
+               close(fd);
+       }
+
+       return -1;
+}
+
+int __accept_candidate_process(int server_fd, int* out_client_fd, int* out_client_pid)
+{
+       int client_fd = -1, client_pid = 0, recv_ret = 0;
+
+       if (server_fd == -1 || out_client_fd == NULL || out_client_pid == NULL)
+       {
+               _E("arguments error!");
+               goto error;
+       }
+
+       client_fd = accept(server_fd, NULL, NULL);
+
+       if (client_fd == -1)
+       {
+               _E("accept error!");
+               goto error;
+       }
+
+       recv_ret = recv(client_fd, &client_pid, sizeof(client_pid), MSG_WAITALL);
+
+       if (recv_ret == -1)
+       {
+               _E("recv error!");
+               goto error;
+       }
+
+       *out_client_fd = client_fd;
+       *out_client_pid = client_pid;
+
+       return *out_client_fd;
+
+error:
+       if (client_fd != -1)
+       {
+               close(client_fd);
+       }
+
+       return -1;
+}
+
+void __refuse_candidate_process(int server_fd)
+{
+       int client_fd = -1;
+
+       if (server_fd == -1)
+       {
+               _E("arguments error!");
+               goto error;
+       }
+
+       client_fd = accept(server_fd, NULL, NULL);
+       if (client_fd == -1)
+       {
+               _E("accept error!");
+               goto error;
+       }
+
+       close(client_fd);
+       _D("refuse connection!");
+
+error:
+       return;
+}
+
+int __send_pkt_raw_data(int client_fd, app_pkt_t *pkt)
+{
+       int send_ret = 0;
+       int pkt_size = 0;
+
+       if (client_fd == -1 || pkt == NULL)
+       {
+               _E("arguments error!");
+               goto error;
+       }
+
+       pkt_size = sizeof(pkt->cmd) + sizeof(pkt->len) + pkt->len;
+
+       send_ret = send(client_fd, pkt, pkt_size, 0);
+       _D("send(%d) : %d / %d", client_fd, send_ret, pkt_size);
+
+       if (send_ret == -1)
+       {
+               _E("send error!");
+               goto error;
+       }
+       else if (send_ret != pkt_size)
+       {
+               _E("send byte fail!");
+               goto error;
+       }
+
+       return 0;
+
+error:
+       return -1;
+}
diff --git a/process_pool/process_pool.h b/process_pool/process_pool.h
new file mode 100644 (file)
index 0000000..a6a2c53
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PROCESS_POOL_H_
+#define __PROCESS_POOL_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif //__cplusplus
+
+#include <app_sock.h>
+
+static const int TYPE1 = 0;
+#ifndef _APPFW_FEATURE_PROCESS_POOL_COMMON
+ #ifdef _APPFW_FEATURE_PROCESS_POOL_HW_RENDERING
+static const int TYPE2 = 1;
+ #endif
+#endif //_APPFW_FEATURE_PROCESS_POOL_COMMON
+
+int  __listen_candidate_process(int type);
+int  __connect_to_launchpad(int type);
+int  __accept_candidate_process(int server_fd, int* out_client_fd, int* out_client_pid);
+void __refuse_candidate_process(int server_fd);
+int  __send_pkt_raw_data(int client_fd, app_pkt_t* pkt);
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+#endif //__PROCESS_POOL_H_
diff --git a/process_pool/process_pool_preload.h b/process_pool/process_pool_preload.h
new file mode 100644 (file)
index 0000000..1fbd55f
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PROCESS_POOL_PRELOAD_H__
+#define __PROCESS_POOL_PRELOAD_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#define PROCESS_POOL_PRELOAD_FILE SHARE_PREFIX"/launchpad-process-pool-preload-list.txt"
+
+static int g_dlopen_size = 5;
+static int g_dlopen_count = 0;
+static void** g_dlopen_handle_list = NULL;
+
+static inline int __preload_save_dlopen_handle(void *handle)
+{
+    if (!handle) {
+        return 1;
+    }
+    if (g_dlopen_count == g_dlopen_size || !g_dlopen_handle_list) {
+        void** tmp =
+            realloc(g_dlopen_handle_list, 2 * g_dlopen_size * sizeof(void *));
+        if (NULL == tmp) {
+            _E("out of memory\n");
+            dlclose(handle);
+            return 1;
+        }
+        g_dlopen_size *= 2;
+        g_dlopen_handle_list = tmp;
+    }
+    g_dlopen_handle_list[g_dlopen_count++] = handle;
+    return 0;
+}
+
+static inline void __preload_fini_for_process_pool(void)
+{
+    int i = 0;
+    if (!g_dlopen_handle_list) {
+        return;
+    }
+    for (i = 0; i < g_dlopen_count; ++i)
+    {
+        void *handle = g_dlopen_handle_list[i];
+        if (handle) {
+            if (0 != dlclose(handle)) {
+                _E("dlclose failed\n");
+            }
+        }
+    }
+    free(g_dlopen_handle_list);
+    g_dlopen_handle_list = NULL;
+    g_dlopen_size = 5;
+    g_dlopen_count = 0;
+}
+
+static inline void __preload_init_for_process_pool(void)
+{
+    if (atexit(__preload_fini_for_process_pool) != 0) {
+        _E("Cannot register atexit callback. Libraries will not be unloaded");
+    }
+
+       void *handle = NULL;
+       char soname[MAX_LOCAL_BUFSZ] = { 0, };
+       FILE *preload_list = NULL;
+
+       preload_list = fopen(PROCESS_POOL_PRELOAD_FILE, "rt");
+       if (preload_list == NULL) {
+               _E("no preload\n");
+               return;
+       }
+
+       while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > 0) {
+        size_t len = strnlen(soname, MAX_LOCAL_BUFSZ);
+        if (len > 0) {
+            soname[len - 1] = '\0';
+        }
+               handle = dlopen((const char *) soname, RTLD_NOW);
+               if (handle == NULL) {
+            _E("dlopen(\"%s\") was failed!", soname);
+            continue;
+        }
+
+        if (__preload_save_dlopen_handle(handle) != 0) {
+            _E("Cannot save handle, no more preloads");
+            break;
+        }
+        _D("preload %s# - handle : %x\n", soname, handle);
+       }
+
+       fclose(preload_list);
+}
+
+#endif //__PROCESS_POOL_PRELOAD_H__
diff --git a/process_pool/smack_util.c b/process_pool/smack_util.c
new file mode 100644 (file)
index 0000000..2342556
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/smack.h>
+#include <dirent.h>
+#include <assert.h>
+
+#include <simple_util.h>
+
+#include "smack_util.h"
+
+#define SMACK_LABEL_LEN        255
+#define FILE_MAX_LEN           1024
+#define MAX_RETRY_CNT          1000
+#define UID_ROOT               0
+
+static char s_smack_label[SMACK_LABEL_LEN + 1] = {0,};
+static int signal_cnt = 0;
+
+static int
+smack_set_label_for_tid(const char *label)
+{
+       int len, fd, ret;
+       char curren_path[FILE_MAX_LEN + 1] = {0,};
+
+       len = strnlen(label, SMACK_LABEL_LEN + 1);
+
+       if (len > SMACK_LABEL_LEN)
+       {
+               return -1;
+       }
+
+       snprintf(curren_path, sizeof(curren_path), "/proc/%d/attr/current", (int)syscall(SYS_gettid));
+       fd = open(curren_path, O_WRONLY);
+       if (fd < 0)
+       {
+               _E("open() failed. path: %s, errno: %d (%s)", curren_path, errno, strerror(errno));
+               return -1;
+       }
+
+       ret = write(fd, label, len);
+       close(fd);
+
+       return (ret < 0) ? -1 : 0;
+}
+
+static void
+SIGUSR1_handler(int signo)
+{
+       if (smack_set_label_for_tid(s_smack_label) != 0)
+       {
+               _E("smack_set_label_for_tid() failed!");
+       }
+
+       SECURE_LOGD("tid: %d, signo: %d", (int)syscall(SYS_gettid), signo);
+       ++signal_cnt;
+}
+
+static int
+set_SIGUSR1_handler()
+{
+#if 1
+       if (signal(SIGUSR1, SIGUSR1_handler) == SIG_ERR)
+       {
+               _E("signal(SIGUSR1) failed.");
+               return -1;
+       }
+#else
+       struct sigaction usr_action;
+       sigset_t usr_mask;
+
+       sigemptyset(&usr_mask);
+       usr_action.sa_handler = SIGUSR1_handler;
+       usr_action.sa_mask = usr_mask;
+       usr_action.sa_flags = 0;
+
+       if (sigaction(SIGUSR1, &usr_action, NULL) != 0)
+       {
+               _E("sigaction(SIGUSR1) failed.");
+               return -1;
+       }
+#endif
+       return 0;
+}
+
+static int
+set_SIGUSR1_to_default()
+{
+       if (signal(SIGUSR1, SIG_DFL) == SIG_ERR)
+       {
+               _E("signal(SIGUSR1, SIG_ERR) failed!");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+send_SIGUSR1_to_threads()
+{
+       int ret;
+       DIR *dir;
+       struct dirent entry, *result;
+       char proc_self_task_path[FILE_MAX_LEN + 1] = {0, };
+       int main_tid = (int)syscall(SYS_gettid);
+
+       sprintf(proc_self_task_path, "/proc/self/task");
+
+       dir = opendir(proc_self_task_path);
+       if (dir)
+       {
+               for (ret = readdir_r(dir, &entry, &result);
+                               result != NULL && ret == 0;
+                               ret = readdir_r(dir, &entry, &result))
+               {
+                       if (strncmp(entry.d_name, ".", 2) == 0 ||
+                               strncmp(entry.d_name, "..", 3) == 0)
+                       {
+                               continue;
+                       }
+
+                       int tid = atoi(entry.d_name);
+                       if (main_tid != tid)
+                       {
+                               SECURE_LOGD("Sending SIGUSR1 signal to the thread (%d).", tid);
+                               if (syscall(SYS_tkill, tid, SIGUSR1) != 0)
+                               {
+                                       _E("tkill(%d, SIGUSR1) failed.", tid);
+                                       closedir(dir);
+                                       return -1;
+                               }
+                       }
+               }
+
+               closedir(dir);
+       }
+       else
+       {
+               _E("opendir(/proc/self/task) failed!");
+               return -1;
+       }
+
+       return 0;
+}
+
+int
+set_app_smack_label(const char* app_path, int type)
+{
+       if (UID_ROOT != getuid() || app_path == NULL)
+       {
+               _E("parameter error!");
+               return -1;
+       }
+
+       // set SIGUSR1 signal handler
+       if (set_SIGUSR1_handler() != 0)
+       {
+               _E("Setting signal hanlder failed.");
+               return -1;
+       }
+
+       // get smack label from app_path
+       char *smack_label = NULL;
+
+       if (smack_lgetlabel(app_path, &smack_label, SMACK_LABEL_EXEC) != 0)
+       {
+               _E("smack_lgetlabel() failed!");
+               goto error;
+       }
+
+       if (smack_label)
+       {
+               strncpy(s_smack_label, smack_label, sizeof(s_smack_label));
+               s_smack_label[SMACK_LABEL_LEN] = '\0';
+
+               free(smack_label);
+               smack_label = NULL;
+       }
+       else
+       {
+               _E("smack_label is NULL!");
+               strcpy(s_smack_label, "");
+       }
+
+       if (type == 2)
+       {
+               signal_cnt = 0;
+
+               if (send_SIGUSR1_to_threads() != 0)
+               {
+                       _E("Sending SIGUSR1 singnal to sub-threads failed.");
+                       goto error;
+               }
+
+               // wait for labeling on each tasks
+               int i = 0;
+               for (i = 0; signal_cnt < (type - 1) && i < MAX_RETRY_CNT; ++i)
+               {
+                       usleep(1000); // 1 ms
+               }
+
+               if (i == MAX_RETRY_CNT)
+               {
+                       _E("Thread subject label update failed.");
+               }
+
+               _D("signal count: %d, launchpad type: %d", signal_cnt, type);
+       }
+
+       // set SIGUSR1 signal defualt handler
+       set_SIGUSR1_to_default();
+
+       return 0;
+
+error:
+       set_SIGUSR1_to_default();
+
+       return -1;
+}
diff --git a/process_pool/smack_util.h b/process_pool/smack_util.h
new file mode 100644 (file)
index 0000000..a19f6e2
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SMACK_UTIL_H
+#define SMACK_UTIL_H
+
+int set_app_smack_label(const char* app_path, int type);
+
+#endif // SMACK_UTIL_H