remove redundant functions
[platform/framework/native/appfw.git] / src / app / FApp_AppEntry.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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  * @file        FApp_AppEntry.cpp
19  * @brief       This is the entry point for the application.
20  */
21
22 #include <cstdio>
23 #include <cstring>
24 #include <cstdlib>
25 #include <algorithm>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <dlfcn.h>
32 #include <limits.h>
33 #include <fcntl.h>
34 #include <sys/prctl.h>
35 #include <linux/capability.h>
36
37 #include <unique_ptr.h>
38
39 #include <dlog.h>
40 #include <privilege-control.h>
41 #include <pkgmgr-info.h>
42
43 #include <FOspConfig.h>
44
45
46 #define LOG_IO_TAG  "LOADER"
47 #define MAX_PACKAGE_ID   20
48 #define MAX_APP_EXECUTABLE_NAME 230
49 #define MAX_PACKAGE_NAME        100
50 #define MAX_PR_NAME     16
51
52
53 #ifdef __cplusplus
54 extern "C"
55 {
56 #endif // __cplusplus
57
58
59 extern int OspMain(int argc, char* pArgv[]) __attribute__((weak));
60 //extern void Osp_Initialize();
61 extern void InitAppInfo(const char* appId, const char* exeName, int argc, char* pArgv[], int fd);
62
63 static void
64 AdjustPrivilege(const char* pkgname)
65 {
66         void* handle = dlopen("libprivilege-control.so.0", RTLD_LAZY | RTLD_LOCAL);
67         if (!handle)
68         {
69                 fprintf(stderr, "Cannot open libprivilege-control.so.0\n");
70                 return;
71         }
72
73         char* msg = 0;
74         dlerror();
75
76         int (* ppriv_func)(const char*) = NULL;
77
78         ppriv_func = reinterpret_cast <int (*)(const char*)>(dlsym(handle, "set_privilege"));
79         msg = dlerror();
80         if (msg != NULL)
81         {
82                 fprintf(stderr, "Dlsym error: %s\n", msg);
83
84                 dlclose(handle);
85                 return;
86         }
87
88         int ret = (*ppriv_func)(pkgname);
89         if (ret < 0)
90         {
91                 fprintf(stderr, "set_privilege() returned %d\n", ret);
92         }
93
94         dlclose(handle);
95 }
96
97 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
98
99 static int
100 AdjustCapability(void)
101 {
102         cap_user_header_t   head = 0;
103         cap_user_data_t data = 0;
104
105         head = static_cast<cap_user_header_t>(malloc(sizeof(*head)));
106         if (head == NULL)
107         {
108                 fprintf(stderr, "Memory allocation failure.\n");
109                 return -1;
110         }
111
112         head->version = _LINUX_CAPABILITY_VERSION;
113         head->pid = getpid();
114
115         data = static_cast<cap_user_data_t>(calloc(sizeof(*data), _LINUX_CAPABILITY_U32S));
116         if (data == NULL)
117         {
118                 fprintf(stderr, "Memory allocation failure.\n");
119
120                 free(head);
121                 return -1;
122         }
123
124         data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
125         data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
126
127         if (capset(head, data) < 0)
128         {
129                 fprintf(stderr, "Capability setting error\n");
130
131                 free(data);
132                 free(head);
133                 return -1;
134         }
135
136         free(data);
137         free(head);
138
139         return 0;
140 }
141
142
143 static int
144 GetAppIdAppExecutableNameFromPathNew(const char appName[], char* appId, char* exeName)
145 {
146         char buffer[PATH_MAX];
147
148         // path is ".../[appid]/bin/[executable_name]"
149
150         memset(buffer, 0, PATH_MAX);
151         const char* pRet = realpath(appName, buffer);
152         if (pRet == NULL)
153         {
154                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, Improper appname %s", appName);
155                 return -1;
156         }
157
158         const char* p = strrchr(buffer, '/');
159         if (p == NULL)
160         {
161                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, Improper appname %s", appName);
162                 return -1;
163         }
164
165         const size_t pathLen = strlen(buffer);
166         const int execLen = strlen(p);
167         if (execLen <= 0 || execLen > PATH_MAX || pathLen > PATH_MAX)
168         {
169                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, Improper appname %s", appName);
170                 return -1;
171         }
172
173         strncpy(exeName, p + 1, execLen);
174         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, exeName is %s", exeName);
175
176         if (pathLen < 1 + 10 + strlen("/bin/") + execLen)
177         {
178                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, Improper appname %s", appName);
179                 return -1;
180         }
181
182         strncpy(appId, p - strlen("bin/") - 10, 10);
183         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, package is %s", appId);
184
185         return 0;
186 }
187
188 static int
189 GetAppIdAppExecutableNameFromPath(const char appName[], char* appId, char* exeName)
190 {
191         const char* begin = NULL;
192         const char* end = NULL;
193         const int path_len = strlen(appName);
194
195         // Calculate the header
196         const char* p = strstr(appName, "/apps/org.tizen.");
197         if (p == NULL)
198         {
199                 return GetAppIdAppExecutableNameFromPathNew(appName, appId, exeName);
200         }
201
202         begin = p + 15;
203
204         end = strchr(begin + 1, '/');
205         if (end == NULL)
206         {
207                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, Improper appname %s", appName);
208                 return -1;
209         }
210
211         int len = end - begin - 1;
212
213         if (len > MAX_PACKAGE_ID)
214         {
215                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, Improper appname %s with length %d", appName, len);
216                 len = MAX_PACKAGE_ID;
217                 //return -1;
218         }
219
220         strncpy(appId, begin + 1, len);
221         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, app is %s", appId);
222
223         int exe_len = 0;
224
225         if (path_len > len + 21)
226         {
227                 exe_len = std::min(MAX_APP_EXECUTABLE_NAME - 1, path_len - len - 21);
228                 strncpy(exeName, end + 5, exe_len);
229         }
230
231         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, exeName is %s", exeName);
232
233         return 0;
234 }
235
236
237 static void
238 PrintArgs(int argc, char* argv[])
239 {
240         const char* p = NULL;
241         int i = 0;
242         do
243         {
244                 p = argv[i];
245                 LOG(LOG_DEBUG, LOG_IO_TAG, "%dth arg : [%s]", i, p);
246                 i++;
247         }
248         while (p);
249 }
250
251 static int
252 DoPreExec(const char* packageName, const char* bin_path)
253 {
254         void* handle = NULL;
255         char* errormsg = 0;
256         int (* DoPreExecFunc)(const char*, const char*) = NULL;
257         int ret = 0;
258
259         handle = dlopen("libosp-env-config.so", RTLD_LAZY | RTLD_GLOBAL);
260         if (!handle)
261         {
262                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io > Failed to dlopen libosp-env-config.so (%s)", dlerror());
263                 return -1;
264         }
265         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io > dlopen() ok");
266
267         DoPreExecFunc = reinterpret_cast <int (*)(const char*, const char*)>(dlsym(handle, "do_pre_exec"));
268         errormsg = dlerror();
269         if (errormsg != NULL)
270         {
271                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io > Failed to dlsym() (%s)", errormsg);
272                 dlclose(handle);
273                 return -1;
274         }
275         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io > dlsym() ok");
276
277         ret = DoPreExecFunc(packageName, bin_path);
278         if (ret < 0)
279         {
280                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io > Failed to do_pre_exe() (%d)", ret);
281         }
282         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io > do_pre_exe() ok");
283
284         dlclose(handle);
285
286         return 0;
287 }
288
289 static void
290 ChangeProcessName(const char* fullPath, int argc, char** const argv)
291 {
292         // http://stupefydeveloper.blogspot.com/2008/10/linux-change-process-name.html
293         // [INFO] While this implementation may not be portable, most program loader does similar work.
294
295         // fullPath should be less than original size
296         const int size = strlen(argv[0]);
297         char* args = argv[0];
298         memset(args, '\0', size);
299         strncpy(args, fullPath, size - 1);
300
301         const char* fileName = NULL;
302         fileName = strrchr(fullPath, '/') + 1;
303         if (fileName)
304         {
305                 char procName[MAX_PR_NAME];
306                 memset(procName, '\0', MAX_PR_NAME);
307
308                 snprintf(procName, MAX_PR_NAME - 1, "%s", fileName);
309                 prctl(PR_SET_NAME, procName);
310                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, %s, %d > Process name %s.", __func__, __LINE__, procName);
311         }
312 }
313
314
315 static void
316 AdjustHwAccInfo(const char* appId)
317 {
318         pkgmgrinfo_appinfo_h appHandle = NULL;
319         int ret = pkgmgrinfo_appinfo_get_appinfo(appId, &appHandle);
320         if (ret != PMINFO_R_OK)
321         {
322                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::App, %s, %d > Getting package info failed for %s.", __func__, __LINE__, appId);
323                 return;
324         }
325
326         pkgmgrinfo_app_hwacceleration hwAcceleration;
327
328         ret = pkgmgrinfo_appinfo_get_hwacceleration(appHandle, &hwAcceleration);
329         if (ret != PMINFO_R_OK)
330         {
331                 LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::App, %s, %d > Getting hwaccel info failed for %s.", __func__, __LINE__, appId);
332                 pkgmgrinfo_appinfo_destroy_appinfo(appHandle);
333         }
334
335         switch(hwAcceleration)
336         {
337         case PMINFO_HWACCELERATION_NOT_USE_GL:
338                 setenv("HWACC", "NOT_USE", 1);
339                 break;
340         case PMINFO_HWACCELERATION_USE_GL:
341                 setenv("HWACC", "USE", 1);
342                 break;
343         case PMINFO_HWACCELERATION_USE_SYSTEM_SETTING:
344                 break;
345         default:
346                 // no need to handle default
347                 break;
348         }
349
350         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::App, %s, %d > HWACC sets for %s with %d.", __func__, __LINE__, appId, hwAcceleration);
351         pkgmgrinfo_appinfo_destroy_appinfo(appHandle);
352 }
353
354
355 /**
356 * The entry function of SLP application called by the operating system.
357 */
358 int _OSP_EXPORT_
359 main(int argc, char* pArgv[])
360 {
361         bool bCommand = false;
362
363         char packageId[MAX_PACKAGE_ID];
364         char exeName[MAX_APP_EXECUTABLE_NAME];
365         char fullPath[PATH_MAX];
366
367         memset(packageId, 0, MAX_PACKAGE_ID);
368         memset(exeName, 0, MAX_APP_EXECUTABLE_NAME);
369         memset(fullPath, 0, PATH_MAX);
370
371         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, %s, %d > executable binary path: %s", __func__, __LINE__, pArgv[0]);
372         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, %s, %d > uid: %d, euid: %d", __func__, __LINE__, getuid(), geteuid());
373
374         const int len = strlen(pArgv[0]);
375         bCommand = (len > 4 && (strncmp(pArgv[0] + len - 4, ".exe", 4) == 0));
376         if (bCommand)
377         {
378                 const int path_size = std::min(PATH_MAX - 1, len - 4);
379                 strncpy(fullPath, pArgv[0], path_size);
380         }
381         else
382         {
383                 strncpy(fullPath, pArgv[0], PATH_MAX - 1);
384         }
385         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, %s, %d > processed binary path: %s", __func__, __LINE__, fullPath);
386
387         // convert package path to packageId
388         GetAppIdAppExecutableNameFromPath(fullPath, packageId, exeName);
389
390         // acquire appId from packageId and exec
391         char appId[MAX_PACKAGE_ID + MAX_APP_EXECUTABLE_NAME + 2] = {0, };
392         strncpy(appId, packageId, 10);
393         appId[10] = '.';
394         strncpy(appId + 11, exeName, MAX_APP_EXECUTABLE_NAME);
395
396
397         if (getuid() == 0)
398         {
399                 // self caging
400                 DoPreExec(packageId, fullPath);
401
402                 // adjust privilege
403                 AdjustPrivilege(packageId);
404         }
405
406         AdjustCapability();
407
408         PrintArgs(argc, pArgv);
409
410         if (bCommand)
411         {
412                 ChangeProcessName(fullPath, argc, pArgv);
413                 pArgv[0] = strdup(fullPath);
414
415         }
416
417         // dlopen will load Osp_Initialize() internally as __attribute__((constructor))
418         //Osp_Initialize();
419         InitAppInfo(packageId, exeName, argc, pArgv, -1);
420
421         AdjustHwAccInfo(appId);
422
423         int r = OspMain(argc, pArgv);
424
425         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, %s, %d > OSP application is terminated.", __func__, __LINE__);
426         LOG(LOG_DEBUG, LOG_IO_TAG, "Tizen::Io, %s, %d > uid: %d, euid: %d", __func__, __LINE__, getuid(), geteuid());
427
428         return r;
429 }
430
431 #ifdef __cplusplus
432 }
433 #endif // __cplusplus