800caa80edc4a78d51abe58e1ac438fd8c1d2d78
[platform/framework/web/wrt.git] / src / wrt-launchpad-daemon / legacy / preload.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17
18 #ifdef PRELOAD_ACTIVATE
19
20 #include <dlfcn.h>
21 #define PRELOAD_FILE        SHARE_PREFIX"/preload_list.txt"
22 #define PRELOAD_FILE_WRT    SHARE_PREFIX"/preload_list_wrt.txt"
23
24 #define EFL_PREINIT_FUNC    "elm_quicklaunch_init"
25 #define EFL_SHUTDOWN_FUNC   "elm_quicklaunch_shutdown"
26
27 static int preload_initialized = 0;
28 static int g_argc;
29 static char **g_argv;
30 static size_t max_cmdline_size = 0;
31
32 static int (*dl_einit) () = NULL;
33 static int (*dl_efini) () = NULL;
34
35 static inline void __preload_init(int argc, char **argv)
36 {
37         void *handle = NULL;
38         char soname[MAX_LOCAL_BUFSZ] = {0, };
39         FILE *preload_list;
40         int (*func)() = NULL;
41         int i;
42
43         g_argc = argc;
44         g_argv = argv;
45         for (i = 0; i < argc; i++) {
46                 max_cmdline_size += (strlen(argv[i]) + 1);
47         }
48         _D("max_cmdline_size = %d", max_cmdline_size);
49
50         preload_list = fopen(PRELOAD_FILE, "rt");
51         if (preload_list == NULL) {
52                 _E("no preload\n");
53                 return;
54         }
55
56         while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > (char*)0) {
57                 soname[MAX_LOCAL_BUFSZ-1] = 0;
58                 handle = dlopen(soname, RTLD_NOW);
59                 if (handle == NULL)
60                         continue;
61                 _D("preload %s# - handle : %x\n", soname, handle);
62
63                 func = dlsym(handle, EFL_PREINIT_FUNC);
64                 if (func != NULL) {
65                         _D("get pre-initialization function\n");
66                         dl_einit = func;
67                         func = dlsym(handle, EFL_SHUTDOWN_FUNC);
68                         if (func != NULL) {
69                                 _D("get shutdown function\n");
70                                 dl_efini = func;
71                         }
72                 }
73         }
74
75         fclose(preload_list);
76         preload_initialized = 1;
77 }
78
79 static inline int preinit_init()
80 {
81         if (dl_einit != NULL)
82                 dl_einit(0, NULL);
83         _D("pre-initialzation on");
84         return 0;
85 }
86
87 static inline int preinit_fini()
88 {
89         if (dl_efini != NULL)
90                 dl_efini();
91         _D("pre-initialization off");
92         return 0;
93 }
94
95 /* TODO : how to set cmdline gracefully ?? */
96 static inline int __change_cmdline(char *cmdline)
97 {
98         if (strlen(cmdline) > max_cmdline_size + 1) {
99                 _E("cmdline exceed max size : %d", max_cmdline_size);
100                 return -1;
101         }
102
103         memset(g_argv[0], '\0', max_cmdline_size);
104         snprintf(g_argv[0], max_cmdline_size, "%s", cmdline);
105
106         return 0;
107 }
108
109 static inline void __preload_exec(int argc, char **argv)
110 {
111         void *handle = NULL;
112         int (*dl_main) (int, char **);
113
114         if (!preload_initialized)
115                 return;
116
117         handle = dlopen(argv[0], RTLD_LAZY | RTLD_GLOBAL);
118         if (handle == NULL) {
119                 return;
120         }
121
122         dl_main = dlsym(handle, "main");
123         if (dl_main != NULL) {
124 #ifndef NATIVE_LAUNCHPAD
125         /* do nothing */
126 #else
127                 if (__change_cmdline(argv[0]) < 0) {
128                         _E("change cmdline fail");
129                         return;
130                 }
131 #endif
132                 dl_main(argc, argv);
133         } else {
134                 _E("dlsym not founded. bad preloaded app - check fpie pie");
135         }
136
137         exit(0);
138 }
139
140 static int g_dlopen_size = 5;
141 static int g_dlopen_count = 0;
142 static void** g_dlopen_handle_list = NULL;
143
144 static inline int __preload_save_dlopen_handle(void *handle)
145 {
146     if (!handle) {
147         return 1;
148     }
149     if (g_dlopen_count == g_dlopen_size || !g_dlopen_handle_list) {
150         void** tmp = realloc(g_dlopen_handle_list, 2 * g_dlopen_size * sizeof(void *));
151         if (NULL == tmp) {
152             _E("out of memory\n");
153             dlclose(handle);
154             return 1;
155         }
156         g_dlopen_size *= 2;
157         g_dlopen_handle_list = tmp;
158     }
159     g_dlopen_handle_list[g_dlopen_count++] = handle;
160     return 0;
161 }
162
163 static inline void __preload_fini_for_wrt()
164 {
165     int i = 0;
166     if (!g_dlopen_handle_list)
167         return;
168     for (i = 0; i < g_dlopen_count; ++i)
169     {
170         void *handle = g_dlopen_handle_list[i];
171         if (handle) {
172             if (0 != dlclose(handle)) {
173                 _E("dlclose failed\n");
174             }
175         }
176     }
177     free(g_dlopen_handle_list);
178     g_dlopen_handle_list = NULL;
179     g_dlopen_size = 5;
180     g_dlopen_count = 0;
181 }
182
183 static inline void __preload_init_for_wrt()
184 {
185     if (0 != atexit(__preload_fini_for_wrt)) {
186         _E("Cannot register atexit callback. Libraries will not be unloaded");
187     }
188     void *handle = NULL;
189     char soname[MAX_LOCAL_BUFSZ];
190     FILE *preload_list;
191
192     preload_list = fopen(PRELOAD_FILE_WRT, "rt");
193     if (preload_list == NULL) {
194         _E("no wrt preload\n");
195         return;
196     }
197
198     while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) != NULL) {
199         size_t len = strnlen(soname, MAX_LOCAL_BUFSZ);
200         if (len > 0)
201             soname[len - 1] = '\0';
202         handle = dlopen(soname, RTLD_NOW|RTLD_GLOBAL);
203         if (handle == NULL)
204             continue;
205         if (0 != __preload_save_dlopen_handle(handle)) {
206             _E("Cannot save handle, no more preloads");
207             break;
208         }
209         _D("preload %s# - handle : %x\n", soname, handle);
210     }
211
212     fclose(preload_list);
213 }
214
215 #else
216
217 static inline void __preload_init(int argc, char **argv);
218 static inline void __preload_exec(int argc, char **argv);
219 static inline void __preload_init_for_wrt();
220
221 #endif
222