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