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