Fix directory hierarchy & cmake configuration files
[platform/core/appfw/launchpad.git] / src / lib / common / src / launchpad_common.c
1 /*
2  * Copyright (c) 2015 - 2016 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 #define _GNU_SOURCE
18
19 #include <string.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/mount.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <sys/xattr.h>
28 #include <errno.h>
29 #include <sys/socket.h>
30 #include <sys/un.h>
31 #include <linux/limits.h>
32 #include <unistd.h>
33 #include <sys/capability.h>
34 #include <tzplatform_config.h>
35 #include <stdio.h>
36 #include <stdbool.h>
37 #include <systemd/sd-journal.h>
38 #include <sys/time.h>
39 #include <sys/resource.h>
40 #include <sys/personality.h>
41 #include <sys/prctl.h>
42 #include <dbus/dbus.h>
43 #include <vconf.h>
44
45 #include "launchpad_common.h"
46 #include "launchpad_types.h"
47 #include "key.h"
48
49 #define MAX_PATH_LEN    1024
50 #define MAX_CMD_BUFSZ 1024
51
52 #define MAX_PENDING_CONNECTIONS 10
53 #define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int) + sizeof(int))
54 #define PATH_AMD_SOCK "/run/aul/daemons/.amd-sock"
55 #define PATH_DEV_NULL "/dev/null"
56 #define MAX_TEP_IS_MOUNT_RETRY_CNT 100
57 #define MAX_PAYLOAD_SIZE (1024 * 1024 * 1)
58
59 #define TEP_BUS_NAME                    "org.tizen.system.deviced"
60 #define TEP_OBJECT_PATH                 "/Org/Tizen/System/DeviceD/Tzip"
61 #define TEP_INTERFACE_NAME              "org.tizen.system.deviced.Tzip"
62 #define TEP_IS_MOUNTED_METHOD           "IsMounted"
63
64 #define APP2SD_BUS_NAME                 "org.tizen.app2sd"
65 #define APP2SD_OBJECT_PATH              "/org/tizen/app2sd"
66 #define APP2SD_INTERFACE_NAME           "org.tizen.app2sd"
67 #define APP2SD_ONDEMANDSETUPINIT_METHOD "OndemandSetupInit"
68 #define APP2SD_RETRY_MAX                5
69 #define APP2SD_WAIT_USEC                (1000000 / 2) /* 0.5 sec */
70
71 #ifndef PR_TASK_PERF_USER_TRACE
72 #define PR_TASK_PERF_USER_TRACE 666
73 #endif
74
75 void _get_cpu_idle(unsigned long long *total, unsigned long long *idle)
76 {
77         FILE *fp;
78         int i;
79         unsigned long long sum = 0;
80         unsigned long long val;
81         unsigned long long iv = 0;
82         char buf[4] = { 0, };
83
84         fp = fopen("/proc/stat", "rt");
85
86         if (fp == NULL)
87                 return;
88
89         if (fscanf(fp, "%3s", buf) == -1) {
90                 fclose(fp);
91                 return;
92         }
93
94         for (i = 0; i < 10; i++) {
95                 if (fscanf(fp, "%lld", &val) == -1) {
96                         fclose(fp);
97                         return;
98                 }
99
100                 if (sum + val < sum) {
101                         _E("overflow");
102                         fclose(fp);
103                         return;
104                 }
105
106                 sum += val;
107                 if (i == 3) /* idle */
108                         iv = val;
109         }
110
111         fclose(fp);
112
113         *total = sum;
114         *idle = iv;
115 }
116
117 int _set_sock_option(int fd, int cli)
118 {
119         struct timeval tv = { 5, 200 * 1000 };  /*  5.2 sec */
120         int size;
121         int flag;
122         int ret;
123
124         size = AUL_SOCK_MAXBUFF;
125         ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
126         if (ret < 0) {
127                 _E("Failed to set SO_SNDBUF option on socket. errno(%d)",
128                                 errno);
129                 return -1;
130         }
131
132         ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
133         if (ret < 0) {
134                 _E("Failed to set SO_RCVBUF option on socket. errno(%d)",
135                                 errno);
136                 return -1;
137         }
138
139         if (cli) {
140                 ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
141                 if (ret < 0) {
142                         _E("Failed to set SO_RCVTIMEO option on socket. " \
143                                         "errno(%d)", errno);
144                         return -1;
145                 }
146
147                 flag = fcntl(fd, F_GETFD);
148                 flag |= FD_CLOEXEC;
149                 ret = fcntl(fd, F_SETFD, flag);
150                 if (ret < 0) {
151                         _E("Failed to manipulate fd(F_SETFD), errno(%d)",
152                                         errno);
153                         return -1;
154                 }
155         }
156
157         return 0;
158 }
159
160 static int __parse_app_path(const char *arg, char *out, int out_size)
161 {
162         register int i;
163         int state = 1;
164         char *start_out = out;
165
166         if (arg == NULL || out == NULL) {
167                 /* Handles null buffer*/
168                 return 0;
169         }
170
171         for (i = 0; out_size > 1; i++) {
172                 switch (state) {
173                 case 1:
174                         switch (arg[i]) {
175                         case ' ':
176                         case '\t':
177                                 state = 5;
178                                 break;
179                         case '\0':
180                                 state = 7;
181                                 break;
182                         case '\"':
183                                 state = 2;
184                                 break;
185                         case '\\':
186                                 state = 4;
187                                 break;
188                         default:
189                                 *out = arg[i];
190                                 out++;
191                                 out_size--;
192                                 break;
193                         }
194                         break;
195                 case 2: /* escape start*/
196                         switch (arg[i]) {
197                         case '\0':
198                                 state = 6;
199                                 break;
200                         case '\"':
201                                 state = 1;
202                                 break;
203                         default:
204                                 *out = arg[i];
205                                 out++;
206                                 out_size--;
207                                 break;
208                         }
209                         break;
210                 case 4: /* character escape*/
211                         if (arg[i] == '\0') {
212                                 state = 6;
213                         } else {
214                                 *out = arg[i];
215                                 out++;
216                                 out_size--;
217                                 state = 1;
218                         }
219                         break;
220                 case 5: /* token*/
221                         if (out != start_out) {
222                                 *out = '\0';
223                                 out_size--;
224                                 return i;
225                         }
226                         i--;
227                         state = 1;
228                         break;
229                 case 6:
230                         return -1;  /* error*/
231                 case 7: /* terminate*/
232                         *out = '\0';
233                         out_size--;
234                         return 0;
235                 default:
236                         state = 6;
237                         break;  /* error*/
238                 }
239         }
240
241         if (out_size == 1)
242                 *out = '\0';
243
244         /* Buffer overflow*/
245         return -2;
246 }
247
248 static int __create_client_socket(const char *path)
249 {
250         struct sockaddr_un addr = { 0, };
251         int retry = CONNECT_RETRY_COUNT;
252         int fd;
253
254         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
255         if (fd < 0) {
256                 _E("Failed to create socket(%s). errno(%d)", path, errno);
257                 return -1;
258         }
259
260         addr.sun_family = AF_UNIX;
261         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
262         while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
263                 if (errno != ETIMEDOUT || retry <= 0) {
264                         _E("Failed to connect socket(%s). errno(%d)",
265                                         path, errno);
266                         close(fd);
267                         return -1;
268                 }
269
270                 usleep(CONNECT_RETRY_TIME);
271                 retry--;
272                 _W("Retry(%d) to connect %s", retry, path);
273         }
274
275         return fd;
276 }
277
278 int _send_cmd_to_amd(int cmd)
279 {
280         app_pkt_t pkt = {0,};
281         int ret;
282         int fd;
283
284         fd = __create_client_socket(PATH_AMD_SOCK);
285         if (fd < 0)
286                 return -1;
287
288         pkt.cmd = cmd;
289         ret = send(fd, &pkt, sizeof(app_pkt_t), MSG_NOSIGNAL);
290         if (ret <= 0) {
291                 _E("Failed to send cmd(%d), errno(%d)", cmd, errno);
292                 close(fd);
293                 return -ECOMM;
294         }
295
296         close(fd);
297         return 0;
298 }
299
300 int _create_server_sock(const char *name)
301 {
302         struct sockaddr_un saddr;
303         int fd;
304
305         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
306         /*  support above version 2.6.27*/
307         if (fd < 0) {
308                 if (errno == EINVAL) {
309                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
310                         if (fd < 0) {
311                                 _E("second chance - socket create error");
312                                 return -1;
313                         }
314                 } else {
315                         _E("socket error");
316                         return -1;
317                 }
318         }
319
320         memset(&saddr, 0, sizeof(saddr));
321         saddr.sun_family = AF_UNIX;
322
323         snprintf(saddr.sun_path, sizeof(saddr.sun_path),
324                         "%s/daemons/%d/%s",
325                         SOCKET_PATH, getuid(), name);
326         unlink(saddr.sun_path);
327
328         if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
329                 _E("bind error");
330                 close(fd);
331                 return -1;
332         }
333
334         if (_set_sock_option(fd, 0) < 0) {
335                 _E("Failed to set sock option");
336                 close(fd);
337                 return -1;
338         }
339
340         if (listen(fd, 128) == -1) {
341                 _E("listen error");
342                 close(fd);
343                 return -1;
344         }
345
346         return fd;
347 }
348
349 app_pkt_t *_recv_pkt_raw(int fd)
350 {
351         int len;
352         int ret;
353         unsigned char buf[AUL_SOCK_MAXBUFF];
354         app_pkt_t *pkt;
355         int cmd;
356         int datalen;
357         int opt;
358
359 retry_recv:
360         /* receive header(cmd, datalen) */
361         len = recv(fd, buf, AUL_PKT_HEADER_SIZE, 0);
362         if (len < 0)
363                 if (errno == EINTR)
364                         goto retry_recv;
365
366         if (len < AUL_PKT_HEADER_SIZE) {
367                 _E("recv error");
368                 return NULL;
369         }
370         memcpy(&cmd, buf, sizeof(int));
371         memcpy(&datalen, buf + sizeof(int), sizeof(int));
372         memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
373
374         if (datalen < 0 || datalen > MAX_PAYLOAD_SIZE) {
375                 _E("Invalid protocol. datalen(%d)", datalen);
376                 return NULL;
377         }
378
379         /* allocate for a null byte */
380         pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
381         if (pkt == NULL) {
382                 _E("failed to alloc app_pkt_t");
383                 return NULL;
384         }
385         pkt->cmd = cmd;
386         pkt->len = datalen;
387         pkt->opt = opt;
388
389         len = 0;
390         while (len != pkt->len) {
391                 ret = recv(fd, pkt->data + len, pkt->len - len, 0);
392                 if (ret < 0) {
393                         _E("recv error %d %d", len, pkt->len);
394                         free(pkt);
395                         return NULL;
396                 }
397                 len += ret;
398                 _D("recv len %d %d", len, pkt->len);
399         }
400
401         return pkt;
402 }
403
404 app_pkt_t *_accept_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
405 {
406         struct sockaddr_un aul_addr = { 0, };
407         int sun_size;
408         app_pkt_t *pkt;
409         int newfd;
410         int cl = sizeof(struct ucred);
411
412         sun_size = sizeof(struct sockaddr_un);
413
414         newfd = accept(fd, (struct sockaddr *)&aul_addr,
415                         (socklen_t *) &sun_size);
416         if (newfd == -1) {
417                 if (errno != EINTR)
418                         _E("accept error");
419                 return NULL;
420         }
421
422         if (getsockopt(newfd, SOL_SOCKET, SO_PEERCRED, cr,
423                         (socklen_t *) &cl) < 0) {
424                 _E("peer information error");
425                 close(newfd);
426                 return NULL;
427         }
428
429         if (_set_sock_option(newfd, 1) < 0) {
430                 _E("Failed to set sock option");
431                 close(newfd);
432                 return NULL;
433         }
434
435         pkt = _recv_pkt_raw(newfd);
436         if (pkt == NULL) {
437                 _E("failed to receive pkt from client");
438                 close(newfd);
439                 return NULL;
440         }
441
442         *clifd = newfd;
443         return pkt;
444 }
445
446 int _send_pkt_raw(int client_fd, app_pkt_t *pkt)
447 {
448         int send_ret = 0;
449         int pkt_size = 0;
450         int sent = 0;
451
452         if (client_fd == -1 || pkt == NULL) {
453                 _E("arguments error!");
454                 return -1;
455         }
456
457         pkt_size = AUL_PKT_HEADER_SIZE + pkt->len;
458
459         while (sent != pkt_size) {
460                 send_ret = send(client_fd, (char *)pkt + sent,
461                                 pkt_size - sent, MSG_NOSIGNAL);
462                 if (send_ret == -1) {
463                         _E("send error! (%d)", errno);
464                         return -1;
465                 }
466
467                 sent += send_ret;
468                 _D("send(%d: ret: %d) : %d / %d",
469                         client_fd, send_ret, sent, pkt_size);
470         }
471
472         return 0;
473 }
474
475 appinfo_t *_appinfo_create(bundle *kb)
476 {
477         appinfo_t *menu_info;
478         const char *ptr = NULL;
479
480         menu_info = calloc(1, sizeof(appinfo_t));
481         if (menu_info == NULL)
482                 return NULL;
483
484         ptr = bundle_get_val(kb, AUL_K_APPID);
485         if (ptr)
486                 menu_info->appid = strdup(ptr);
487         ptr = bundle_get_val(kb, AUL_K_EXEC);
488         if (ptr)
489                 menu_info->app_path = strdup(ptr);
490         if (menu_info->app_path != NULL)
491                 menu_info->original_app_path = strdup(menu_info->app_path);
492         ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
493         if (ptr)
494                 menu_info->pkg_type = strdup(ptr);
495         ptr = bundle_get_val(kb, AUL_K_APP_TYPE);
496         if (ptr)
497                 menu_info->app_type = strdup(ptr);
498         ptr = bundle_get_val(kb, AUL_K_HWACC);
499         if (ptr)
500                 menu_info->hwacc = strdup(ptr);
501         ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
502         if (ptr)
503                 menu_info->taskmanage = strdup(ptr);
504         ptr = bundle_get_val(kb, AUL_K_PKGID);
505         if (ptr)
506                 menu_info->pkgid = strdup(ptr);
507         ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
508         if (ptr)
509                 menu_info->comp_type = strdup(ptr);
510         ptr = bundle_get_val(kb, AUL_K_INTERNAL_POOL);
511         if (ptr)
512                 menu_info->internal_pool = strdup(ptr);
513         ptr = bundle_get_val(kb, AUL_K_ROOT_PATH);
514         if (ptr)
515                 menu_info->root_path = strdup(ptr);
516
517         ptr = bundle_get_val(kb, AUL_K_LOADER_NAME);
518         if (ptr)
519                 menu_info->loader_name = strdup(ptr);
520
521         ptr = bundle_get_val(kb, AUL_K_IS_GLOBAL);
522         if (ptr && strcmp(ptr, "true") == 0)
523                 menu_info->global = true;
524         else
525                 menu_info->global = false;
526
527         if (!_appinfo_get_app_path(menu_info)) {
528                 _appinfo_free(menu_info);
529                 return NULL;
530         }
531
532         return menu_info;
533 }
534
535 char *_appinfo_get_app_path(appinfo_t *menu_info)
536 {
537         int i = 0;
538         int path_len = -1;
539         char *tmp_app_path;
540
541         if (!menu_info || menu_info->app_path == NULL)
542                 return NULL;
543
544         while (menu_info->app_path[i] != 0) {
545                 if (menu_info->app_path[i] == ' '
546                     || menu_info->app_path[i] == '\t') {
547                         path_len = i;
548                         break;
549                 }
550                 i++;
551         }
552
553         if (path_len == 0) {
554                 free(menu_info->app_path);
555                 menu_info->app_path = NULL;
556         } else if (path_len > 0) {
557                 tmp_app_path = malloc(sizeof(char) * (path_len + 1));
558                 if (tmp_app_path == NULL)
559                         return NULL;
560                 snprintf(tmp_app_path, path_len + 1, "%s", menu_info->app_path);
561                 free(menu_info->app_path);
562                 menu_info->app_path = tmp_app_path;
563         }
564
565         return menu_info->app_path;
566 }
567
568 void _appinfo_free(appinfo_t *menu_info)
569 {
570         if (menu_info == NULL)
571                 return;
572
573         if (menu_info->appid != NULL)
574                 free(menu_info->appid);
575         if (menu_info->app_path != NULL)
576                 free(menu_info->app_path);
577         if (menu_info->original_app_path != NULL)
578                 free(menu_info->original_app_path);
579         if (menu_info->pkg_type != NULL)
580                 free(menu_info->pkg_type);
581         if (menu_info->app_type != NULL)
582                 free(menu_info->app_type);
583         if (menu_info->hwacc != NULL)
584                 free(menu_info->hwacc);
585         if (menu_info->taskmanage != NULL)
586                 free(menu_info->taskmanage);
587         if (menu_info->pkgid != NULL)
588                 free(menu_info->pkgid);
589         if (menu_info->comp_type != NULL)
590                 free(menu_info->comp_type);
591         if (menu_info->internal_pool != NULL)
592                 free(menu_info->internal_pool);
593         if (menu_info->root_path != NULL)
594                 free(menu_info->root_path);
595         if (menu_info->loader_name != NULL)
596                 free(menu_info->loader_name);
597
598         free(menu_info);
599 }
600
601 static bool __validate_bundle_key(const char *key)
602 {
603         if (!key)
604                 return false;
605
606         if (!strncmp(key, "__AUL_", strlen("__AUL_")))
607                 return false;
608
609         if (!strncmp(key, "__APP_SVC_", strlen("__APP_SVC_")))
610                 return false;
611
612         return true;
613 }
614
615 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *menu_info, int cmd)
616 {
617         char *ptr;
618         char exe[MAX_PATH_LEN];
619         int flag;
620         char key[256];
621         char value[256];
622
623         bundle_del(kb, AUL_K_APPID);
624         bundle_del(kb, AUL_K_EXEC);
625         bundle_del(kb, AUL_K_APP_TYPE);
626         bundle_del(kb, AUL_K_PACKAGETYPE);
627         bundle_del(kb, AUL_K_TASKMANAGE);
628         bundle_del(kb, AUL_K_PKGID);
629         bundle_del(kb, AUL_K_COMP_TYPE);
630
631         /* Parse app_path to retrieve default bundle*/
632         if (cmd == PAD_CMD_LAUNCH) {
633                 ptr = menu_info->original_app_path;
634                 flag = __parse_app_path(ptr, exe, sizeof(exe));
635                 if (flag > 0) {
636                         ptr += flag;
637                         SECURE_LOGD("parsing app_path: EXEC - %s", exe);
638
639                         do {
640                                 flag = __parse_app_path(ptr, key, sizeof(key));
641                                 if (flag <= 0)
642                                         break;
643                                 ptr += flag;
644
645                                 flag = __parse_app_path(ptr, value,
646                                                 sizeof(value));
647                                 if (flag < 0)
648                                         break;
649                                 ptr += flag;
650
651                                 /*bundle_del(kb, key);*/
652                                 if (__validate_bundle_key(key))
653                                         bundle_add(kb, key, value);
654                         } while (flag > 0);
655                 } else if (flag == 0)
656                         _D("parsing app_path: No arguments");
657                 else
658                         _D("parsing app_path: Invalid argument");
659         }
660 }
661
662 int _connect_to_launchpad(int type, int id)
663 {
664         char path[PATH_MAX];
665         int client_pid;
666         int send_ret;
667         int fd;
668
669         _D("[launchpad] enter, type: %d", type);
670
671         snprintf(path, sizeof(path), "%s/daemons/%d/%s%d-%d",
672                         SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
673                         type, id);
674         fd = __create_client_socket(path);
675         if (fd < 0)
676                 return -1;
677
678         client_pid = getpid();
679         send_ret = send(fd, &client_pid, sizeof(client_pid), MSG_NOSIGNAL);
680         _D("send(%d) : %d", client_pid, send_ret);
681         if (send_ret == -1) {
682                 _E("send error(%d)", errno);
683                 close(fd);
684                 return -1;
685         }
686
687         SECURE_LOGD("[launchpad] done, connect fd: %d", fd);
688         return fd;
689 }
690
691 #ifdef TIZEN_FEATURE_SET_PERSONALITY_32
692 static void __set_execution_domain(void)
693 {
694         char err_buf[1024];
695         int res;
696
697         res = personality(PER_LINUX32);
698         if (res < 0) {
699                 _E("personality() failed,  error: %d (%s)",
700                                 errno,
701                                 strerror_r(errno, err_buf, sizeof(err_buf)));
702         }
703 }
704 #endif /* TIZEN_FEATURE_SET_PERSONALITY_32 */
705
706 static void __set_lang_env(void)
707 {
708         const char *lang;
709
710         lang = getenv("LANG");
711         if (!lang) {
712                 lang = "en_US.UTF-8";
713                 setenv("LANG", lang, 1);
714         }
715
716         setenv("LANGUAGE", lang, 1);
717         setenv("LC_MESSAGES", lang, 1);
718         setenv("LC_ALL", lang, 1);
719 }
720
721 static void __set_region_env(void)
722 {
723         const char *region;
724
725         region = getenv("LC_CTYPE");
726         if (!region) {
727                 region = "en_US.UTF-8";
728                 setenv("LC_CTYPE", region, 1);
729         }
730
731         setenv("LC_NUMERIC", region, 1);
732         setenv("LC_TIME", region, 1);
733         setenv("LC_COLLATE", region, 1);
734         setenv("LC_MONETARY", region, 1);
735         setenv("LC_PAPER", region, 1);
736         setenv("LC_NAME", region, 1);
737         setenv("LC_ADDRESS", region, 1);
738         setenv("LC_TELEPHONE", region, 1);
739         setenv("LC_MEASUREMENT", region, 1);
740         setenv("LC_IDENTIFICATION", region, 1);
741 }
742
743 void _set_env(appinfo_t *menu_info, bundle *kb)
744 {
745         const char *str;
746         char buf[MAX_LOCAL_BUFSZ];
747
748         str = bundle_get_val(kb, AUL_K_STARTTIME);
749         if (str != NULL)
750                 setenv("APP_START_TIME", str, 1);
751
752         if (menu_info->hwacc != NULL)
753                 setenv("HWACC", menu_info->hwacc, 1);
754         if (menu_info->taskmanage != NULL)
755                 setenv("TASKMANAGE", menu_info->taskmanage, 1);
756         if (menu_info->root_path != NULL)
757                 setenv("AUL_ROOT_PATH", menu_info->root_path, 1);
758         if (menu_info->appid != NULL)
759                 setenv("AUL_APPID", menu_info->appid, 1);
760         if (menu_info->pkgid != NULL)
761                 setenv("AUL_PKGID", menu_info->pkgid, 1);
762         if (menu_info->app_type != NULL)
763                 setenv("RUNTIME_TYPE", menu_info->app_type, 1);
764
765         str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
766         if (str != NULL)
767                 setenv("WAYLAND_DISPLAY", str, 1);
768
769         str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
770         if (str != NULL)
771                 setenv("XDG_RUNTIME_DIR", str, 1);
772
773         str = bundle_get_val(kb, AUL_K_API_VERSION);
774         if (str != NULL)
775                 setenv("TIZEN_API_VERSION", str, 1);
776
777         snprintf(buf, sizeof(buf), "%d", getpid());
778         setenv("AUL_PID", buf, 1);
779
780         __set_lang_env();
781         __set_region_env();
782 #ifdef TIZEN_FEATURE_SET_PERSONALITY_32
783         __set_execution_domain();
784 #endif /* TIZEN_FEATURE_SET_PERSONALITY_32 */
785 }
786
787 char **_create_argc_argv(bundle *kb, int *margc)
788 {
789         char **argv;
790         int argc;
791
792         argc = bundle_export_to_argv(kb, &argv);
793
794         *margc = argc;
795         return argv;
796 }
797
798 char *_get_libdir(const char *path)
799 {
800         char *path_dup;
801         char buf[PATH_MAX];
802         char *ptr;
803
804         if (path == NULL)
805                 return NULL;
806         path_dup = strdup(path);
807         if (path_dup == NULL)
808                 return NULL;
809         ptr = strrchr(path_dup, '/');
810         if (ptr == NULL) {
811                 free(path_dup);
812                 return NULL;
813         }
814
815         *ptr = '\0';
816
817         snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
818         free(path_dup);
819
820         if (access(buf, F_OK) == -1)
821                 return NULL;
822
823         return strdup(buf);
824 }
825
826 static int __delete_dir(const char *path)
827 {
828         DIR *dp;
829         struct dirent *dentry = NULL;
830         char buf[PATH_MAX];
831         struct stat statbuf;
832         int ret;
833
834         if (path == NULL)
835                 return -1;
836
837         dp = opendir(path);
838         if (dp == NULL)
839                 return -1;
840
841         while ((dentry = readdir(dp)) != NULL) {
842                 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
843                         continue;
844
845                 snprintf(buf, sizeof(buf), "%s/%s", path, dentry->d_name);
846                 ret = stat(buf, &statbuf);
847                 if (ret == 0) {
848                         if (S_ISDIR(statbuf.st_mode))
849                                 __delete_dir(buf);
850                         else
851                                 unlink(buf);
852                 }
853         }
854
855         rmdir(path);
856         closedir(dp);
857
858         return 0;
859 }
860
861 int _delete_sock_path(int pid, uid_t uid)
862 {
863         char path[PATH_MAX];
864         int r;
865
866         snprintf(path, sizeof(path), "/run/aul/apps/%d/%d", uid, pid);
867         r = access(path, F_OK);
868         if (r != 0) {
869                 if (errno != ENOENT)
870                         _E("Failed to access %s. errno(%d)", path, errno);
871         } else {
872                 __delete_dir(path);
873         }
874
875         if (access(path, F_OK) == 0) {
876                 _E("Failed to delete %s", path);
877                 return -1;
878         }
879
880         return 0;
881 }
882
883 int _close_all_fds(void)
884 {
885         DIR *dp;
886         struct dirent *dentry = NULL;
887         int fd;
888         int max_fd;
889         int aul_fd = -1;
890         const char *aul_listen_fd;
891
892         aul_listen_fd = getenv("AUL_LISTEN_FD");
893         if (aul_listen_fd)
894                 aul_fd = atoi(aul_listen_fd);
895
896         dp = opendir("/proc/self/fd");
897         if (dp == NULL) {
898                 /* fallback */
899                 max_fd = sysconf(_SC_OPEN_MAX);
900                 for (fd = 3; fd < max_fd; fd++) {
901                         if (fd != aul_fd)
902                                 close(fd);
903                 }
904
905                 return 0;
906         }
907
908         while ((dentry = readdir(dp)) != NULL) {
909                 if (!isdigit(dentry->d_name[0]))
910                         continue;
911
912                 fd = atoi(dentry->d_name);
913                 if (fd < 3)
914                         continue;
915
916                 if (fd == dirfd(dp) || fd == aul_fd)
917                         continue;
918
919                 close(fd);
920         }
921         closedir(dp);
922
923         return 0;
924 }
925
926 static int __redirect_stdin(void)
927 {
928         int ret;
929         int fd;
930
931         fd = open(PATH_DEV_NULL, O_RDONLY | O_NOCTTY);
932         if (fd < 0) {
933                 ret = -errno;
934                 _E("open(%s) is failed. errno(%d)", PATH_DEV_NULL, errno);
935                 return ret;
936         }
937
938         ret = dup2(fd, STDIN_FILENO);
939         if (ret < 0)
940                 _W("dup2(%d, 0) is failed. errno(%d)", fd, errno);
941
942         close(fd);
943         return ret;
944 }
945
946 static int __redirect_stdout(const char *ident)
947 {
948         int ret;
949         int fd;
950
951         fd = sd_journal_stream_fd(ident, LOG_INFO, 0);
952         if (fd < 0) {
953                 if (fd != -ENOENT)
954                         _W("sd_journal_stream_fd() is failed. error(%d)", fd);
955                 fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY);
956                 if (fd < 0) {
957                         ret = -errno;
958                         _E("open(%s) is failed. errno(%d)",
959                                         PATH_DEV_NULL, errno);
960                         close(STDOUT_FILENO);
961                         return ret;
962                 }
963         }
964
965         ret = dup2(fd, STDOUT_FILENO);
966         if (ret < 0) {
967                 ret = -errno;
968                 _E("dup(%d, 1) is failed. errno(%d)", fd, errno);
969                 close(STDOUT_FILENO);
970         }
971
972         close(fd);
973         return ret;
974 }
975
976 static int __redirect_stderr(const char *ident)
977 {
978         int ret;
979         int fd;
980
981         fd = sd_journal_stream_fd(ident, LOG_WARNING, 0);
982         if (fd < 0) {
983                 if (fd != -ENOENT)
984                         _W("sd_journal_stream_fd() is failed. error(%d)", fd);
985                 fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY);
986                 if (fd < 0) {
987                         ret = -errno;
988                         _E("open(%s) is failed. errno(%d)",
989                                         PATH_DEV_NULL, errno);
990                         close(STDERR_FILENO);
991                         return ret;
992                 }
993         }
994
995         ret = dup2(fd, STDERR_FILENO);
996         if (ret < 0) {
997                 ret = -errno;
998                 _E("dup(%d, 2) is failed. errno(%d)", fd, errno);
999                 close(STDERR_FILENO);
1000         }
1001
1002         close(fd);
1003         return ret;
1004
1005 }
1006
1007 int _setup_stdio(const char *ident)
1008 {
1009         int ret;
1010
1011         ret = __redirect_stdin();
1012         if (ret < 0)
1013                 return ret;
1014
1015         ret = __redirect_stdout(ident);
1016         if (ret < 0)
1017                 return ret;
1018
1019         ret = __redirect_stderr(ident);
1020         if (ret < 0)
1021                 return ret;
1022
1023         return 0;
1024 }
1025
1026 int _set_priority(int prio)
1027 {
1028         int r;
1029
1030         r = setpriority(PRIO_PGRP, 0, prio);
1031         if (r < 0) {
1032                 SECURE_LOGE("Failed to set process(%d) priority(%d) - err(%d)",
1033                                 getpid(), prio, errno);
1034         }
1035
1036         return r;
1037 }
1038
1039 static int __dbus_send_message(DBusMessage *callback(void *), void *user_data,
1040                 int timeout, int *result)
1041 {
1042         DBusError err;
1043         DBusConnection *conn;
1044         DBusMessage *msg = NULL;
1045         DBusMessageIter args;
1046         DBusPendingCall *pending = NULL;
1047         dbus_bool_t r;
1048         dbus_int32_t i;
1049         int ret = 0;
1050
1051         dbus_error_init(&err);
1052         conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
1053         if (!conn) {
1054                 _E("Failed to connect to D-Bus Daemon");
1055                 ret = -1;
1056                 goto end;
1057         }
1058
1059         msg = callback(user_data);
1060         if (!msg) {
1061                 _E("Message is nullptr");
1062                 goto end;
1063         }
1064
1065         r = dbus_connection_send_with_reply(conn, msg, &pending, timeout);
1066         if (!r || !pending) {
1067                 _E("Failed to send message");
1068                 ret = -1;
1069                 goto end;
1070         }
1071
1072         dbus_connection_flush(conn);
1073         dbus_message_unref(msg);
1074
1075         dbus_pending_call_block(pending);
1076         msg = dbus_pending_call_steal_reply(pending);
1077         if (!msg) {
1078                 _E("Failed to get reply message");
1079                 ret = -1;
1080                 goto end;
1081         }
1082
1083         dbus_pending_call_unref(pending);
1084
1085         if (!dbus_message_iter_init(msg, &args)) {
1086                 _E("Message has no arguments!");
1087                 ret = -1;
1088         } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_INT32) {
1089                 _E("Argument is not integer! type(%d)",
1090                                 dbus_message_iter_get_arg_type(&args));
1091                 ret = -1;
1092         } else {
1093                 dbus_message_iter_get_basic(&args, &i);
1094                 *result = i;
1095         }
1096
1097         _D("Result: %d", *result);
1098 end:
1099         if (msg)
1100                 dbus_message_unref(msg);
1101
1102         if (conn)
1103                 dbus_connection_close(conn);
1104
1105         if (dbus_error_is_set(&err)) {
1106                 _E("D-Bus error(%s)", err.message);
1107                 dbus_error_free(&err);
1108         }
1109
1110         return ret;
1111 }
1112
1113 static DBusMessage *__create_tep_mount_message(void *user_data)
1114 {
1115         DBusMessage *message;
1116         DBusMessageIter args;
1117         dbus_bool_t r;
1118         const char *tep_path = (const char *)user_data;
1119
1120         message = dbus_message_new_method_call(TEP_BUS_NAME,
1121                         TEP_OBJECT_PATH,
1122                         TEP_INTERFACE_NAME,
1123                         TEP_IS_MOUNTED_METHOD);
1124         if (!message) {
1125                 _E("Message is nullptr");
1126                 return NULL;
1127         }
1128
1129         dbus_message_iter_init_append(message, &args);
1130         r = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &tep_path);
1131         if (!r) {
1132                 _E("Out of memory");
1133                 dbus_message_unref(message);
1134                 return NULL;
1135         }
1136
1137         return message;
1138 }
1139
1140 static int __is_tep_mount_done(const char *tep_path)
1141 {
1142         int result = -1;
1143         int ret;
1144
1145         ret = __dbus_send_message(__create_tep_mount_message,
1146                         (void *)tep_path, 500, &result);
1147         if (ret != 0)
1148                 _E("Failed to send message");
1149
1150         return result;
1151 }
1152
1153 static int __check_tep_mount(const char *tep_path)
1154 {
1155         int r;
1156         int cnt = 0;
1157
1158         if (!tep_path)
1159                 return 0;
1160
1161         while (cnt < MAX_TEP_IS_MOUNT_RETRY_CNT) {
1162                 r = __is_tep_mount_done(tep_path);
1163                 if (r == 1)
1164                         break;
1165                 usleep(50 * 1000);
1166                 cnt++;
1167         }
1168
1169         if (r != 1) {
1170                 _E("Not able to mount within 5 sec: %s", tep_path);
1171                 return -1;
1172         }
1173
1174         return 0;
1175 }
1176
1177 int _wait_tep_mount(bundle *b)
1178 {
1179         int r;
1180         int i;
1181         int len = 0;
1182         const char **tep_paths;
1183
1184         tep_paths = bundle_get_str_array(b, AUL_K_TEP_PATH, &len);
1185         if (!tep_paths)
1186                 return 0;
1187
1188         for (i = 0; i < len; ++i) {
1189                 r = __check_tep_mount(tep_paths[i]);
1190                 if (r < 0)
1191                         return -1;
1192         }
1193
1194         _I("Mount has been done.");
1195         return 0;
1196 }
1197
1198 static int __create_app_socket(int pid, uid_t uid)
1199 {
1200         int fd;
1201         char path[PATH_MAX];
1202         struct sockaddr_un addr = {
1203                 .sun_family = AF_UNIX,
1204         };
1205
1206         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
1207         if (fd < 0) {
1208                 if (errno == EINVAL) {
1209                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
1210                         if (fd < 0) {
1211                                 _E("Second chance - socket create errno(%d)",
1212                                                 errno);
1213                                 return -1;
1214                         }
1215                 } else {
1216                         _E("Failed to create socket. errno(%d)", errno);
1217                         return -1;
1218                 }
1219         }
1220
1221         snprintf(path, sizeof(path), "/run/aul/apps/%u/%d", uid, pid);
1222         if (mkdir(path, 0700) != 0) {
1223                 if (errno == EEXIST) {
1224                         if (access(path, R_OK) != 0) {
1225                                 _E("Failed to access %s. errno(%d)",
1226                                                 path, errno);
1227                                 close(fd);
1228                                 return -errno;
1229                         }
1230                 } else {
1231                         _E("Failed to access %s. errno(%d)", path, errno);
1232                         close(fd);
1233                         return -1;
1234                 }
1235         }
1236
1237         snprintf(addr.sun_path, sizeof(addr.sun_path),
1238                         "/run/aul/apps/%u/%d/.app-sock", uid, pid);
1239         unlink(addr.sun_path);
1240
1241         if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1242                 _E("Failed to bind socket(%d), errno(%d)", fd, errno);
1243                 close(fd);
1244                 return -1;
1245         }
1246
1247         if (_set_sock_option(fd, 0) < 0) {
1248                 _E("Failed to set sock option");
1249                 close(fd);
1250                 return -1;
1251         }
1252
1253         if (listen(fd, 128) < 0) {
1254                 _E("Failed to listen %d, errno(%d)", fd, errno);
1255                 close(fd);
1256                 return -1;
1257         }
1258
1259         return fd;
1260 }
1261
1262 int _prepare_app_socket(void)
1263 {
1264         int fd;
1265         char buf[12];
1266
1267         fd = __create_app_socket(getpid(), getuid());
1268         if (fd < 0)
1269                 return fd;
1270
1271         snprintf(buf, sizeof(buf), "%d", fd);
1272         setenv("AUL_LISTEN_FD", buf, 1);
1273
1274         return 0;
1275 }
1276
1277 struct package_info_s {
1278         const char *id;
1279         uid_t uid;
1280 };
1281
1282 static DBusMessage *__create_app2sd_message(void *user_data)
1283 {
1284         struct package_info_s *pkg_info = (struct package_info_s *)user_data;
1285         DBusMessage *message;
1286         DBusMessageIter args;
1287         dbus_bool_t r;
1288
1289         _D("[__APP2SD__] package(%s), uid(%u)", pkg_info->id, pkg_info->uid);
1290
1291         message = dbus_message_new_method_call(APP2SD_BUS_NAME,
1292                         APP2SD_OBJECT_PATH,
1293                         APP2SD_INTERFACE_NAME,
1294                         APP2SD_ONDEMANDSETUPINIT_METHOD);
1295         if (!message) {
1296                 _E("Message is nullptr");
1297                 return NULL;
1298         }
1299
1300         dbus_message_iter_init_append(message, &args);
1301         r = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,
1302                         &pkg_info->id);
1303         if (!r) {
1304                 _E("Failed to append pkgid");
1305                 dbus_message_unref(message);
1306                 return NULL;
1307         }
1308
1309         r = dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32,
1310                         &pkg_info->uid);
1311         if (!r) {
1312                 _E("Failed to append uid");
1313                 dbus_message_unref(message);
1314                 return NULL;
1315         }
1316
1317         return message;
1318 }
1319
1320 int _enable_external_pkg(bundle *b, const char *pkgid, uid_t pkg_uid)
1321 {
1322         const char *installed_storage;
1323         int retry_cnt = 0;
1324         int result = -1;
1325         int ret;
1326         struct package_info_s pkg_info = {
1327                 .id = pkgid,
1328                 .uid = pkg_uid
1329         };
1330
1331         installed_storage = bundle_get_val(b, AUL_K_INSTALLED_STORAGE);
1332         if (!installed_storage || strcmp(installed_storage, "external") != 0)
1333                 return 0;
1334
1335         do {
1336                 ret = __dbus_send_message(__create_app2sd_message,
1337                                 &pkg_info, 500, &result);
1338                 if (ret != 0) {
1339                         _E("Failed to send message");
1340                         retry_cnt++;
1341                         usleep(APP2SD_WAIT_USEC);
1342                         continue;
1343                 }
1344
1345                 break;
1346         } while (retry_cnt <= APP2SD_RETRY_MAX);
1347
1348         _D("[__APP2SD__] result(%d)", result);
1349
1350         return result;
1351 }
1352
1353 int _verify_proc_caps(void)
1354 {
1355         cap_t cap_d;
1356         cap_flag_value_t eff_state;
1357         cap_flag_value_t inh_state;
1358         cap_value_t value = CAP_SETGID;
1359         int r;
1360
1361         cap_d = cap_get_proc();
1362         if (!cap_d) {
1363                 _E("Failed to get cap from proc. pid(%d)", getpid());
1364                 return -1;
1365         }
1366
1367         r = cap_get_flag(cap_d, value, CAP_INHERITABLE, &inh_state);
1368         if (r != 0) {
1369                 _E("Failed to get cap inh - errno(%d)", errno);
1370                 cap_free(cap_d);
1371                 return -1;
1372         }
1373
1374         r = cap_get_flag(cap_d, value, CAP_EFFECTIVE, &eff_state);
1375         if (r != 0) {
1376                 _E("Failed to get cap eff - errno(%d)", errno);
1377                 cap_free(cap_d);
1378                 return -1;
1379         }
1380
1381         if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
1382                 _E("The process(%d) doesn't have %d cap",
1383                                 getpid(), value);
1384                 cap_free(cap_d);
1385                 return -1;
1386         }
1387         cap_free(cap_d);
1388
1389         return 0;
1390 }
1391
1392 int _prepare_id_file(void)
1393 {
1394         char path[PATH_MAX];
1395         int fd;
1396
1397         snprintf(path, sizeof(path), "/run/aul/apps/%u/%d/%s",
1398                         getuid(), getpid(), getenv("AUL_APPID"));
1399         fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0600);
1400         if (fd < 0) {
1401                 _E("Failed to create %s. errno(%d)", path, errno);
1402                 return -1;
1403         }
1404         close(fd);
1405
1406         return 0;
1407 }
1408
1409 static int __send_raw(int fd, int cmd, unsigned char *data, int datalen)
1410 {
1411         app_pkt_t *pkt;
1412         int ret;
1413
1414         pkt = (app_pkt_t *)calloc(1, sizeof(app_pkt_t) + datalen);
1415         if (!pkt) {
1416                 _E("Out of memory");
1417                 return -ENOMEM;
1418         }
1419
1420         pkt->cmd = cmd;
1421         pkt->len = datalen;
1422         if (data)
1423                 memcpy(pkt->data, data, pkt->len);
1424
1425         ret = _send_pkt_raw(fd, pkt);
1426         if (ret < 0) {
1427                 free(pkt);
1428                 return -1;
1429         }
1430
1431         free(pkt);
1432
1433         return 0;
1434 }
1435
1436 int _send_message_to_logger(const char *tag, const char *format, ...)
1437 {
1438         char fmt[PATH_MAX - 256];
1439         char buf[PATH_MAX];
1440         va_list ap;
1441         int ret;
1442         int fd;
1443
1444         snprintf(buf, sizeof(buf), "%s/daemons/%u/.launchpad-logger-sock",
1445                         SOCKET_PATH, getuid());
1446         fd = __create_client_socket(buf);
1447         if (fd < 0)
1448                 return -1;
1449
1450         va_start(ap, format);
1451         vsnprintf(fmt, sizeof(fmt), format, ap);
1452         va_end(ap);
1453
1454         snprintf(buf, sizeof(buf), "%s: %s", tag, fmt);
1455         ret = __send_raw(fd, 0, (unsigned char *)buf, strlen(buf) + 1);
1456         if (ret < 0) {
1457                 close(fd);
1458                 return -1;
1459         }
1460
1461         close(fd);
1462
1463         return 0;
1464 }
1465
1466 void _print_hwc_log(const char *format, ...)
1467 {
1468         char buf[1024];
1469         va_list ap;
1470
1471         va_start(ap, format);
1472         vsnprintf(buf, sizeof(buf), format, ap);
1473         va_end(ap);
1474
1475         prctl(PR_TASK_PERF_USER_TRACE, buf, strlen(buf));
1476 }