Bump up efl module version.
[platform/core/appfw/launchpad.git] / src / launchpad.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 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/prctl.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <sys/stat.h>
26 #include <sys/capability.h>
27 #include <sched.h>
28 #include <stdbool.h>
29 #include <malloc.h>
30 #include <bundle_internal.h>
31 #include <security-manager.h>
32 #include <time.h>
33 #include <systemd/sd-daemon.h>
34 #include <glib.h>
35 #include <linux/limits.h>
36 #include <ttrace.h>
37 #include <vconf.h>
38 #include <math.h>
39 #include <trust-anchor.h>
40
41 #include "perf.h"
42 #include "launchpad_common.h"
43 #include "launchpad_signal.h"
44 #include "key.h"
45 #include "launchpad.h"
46 #include "loader_info.h"
47 #include "launcher_info.h"
48 #include "launchpad_debug.h"
49
50 #define AUL_PR_NAME         16
51 #define EXEC_CANDIDATE_EXPIRED 5
52 #define EXEC_CANDIDATE_WAIT 1
53 #define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a))
54 #define CANDIDATE_NONE 0
55 #define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock"
56 #define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock"
57 #define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader"
58 #define LOADER_INFO_PATH        "/usr/share/aul"
59 #define LAUNCHER_INFO_PATH      LOADER_INFO_PATH
60 #define REGULAR_UID_MIN 5000
61 #define PAD_ERR_FAILED                  -1
62 #define PAD_ERR_REJECTED                -2
63 #define PAD_ERR_INVALID_ARGUMENT        -3
64 #define PAD_ERR_INVALID_PATH            -4
65 #define CPU_CHECKER_TIMEOUT             1000
66 #define PI                              3.14159265
67
68 enum candidate_process_state_e {
69         CANDIDATE_PROCESS_STATE_RUNNING,
70         CANDIDATE_PROCESS_STATE_PAUSED,
71 };
72
73 typedef struct {
74         int type;
75         bool prepared;
76         int pid;
77         int loader_id;
78         int caller_pid;
79         int send_fd;
80         int last_exec_time;
81         guint source;
82         guint timer;
83         char *loader_path;
84         char *loader_extra;
85         int detection_method;
86         int timeout_val;
87         unsigned long long cpu_total_time;
88         unsigned long long cpu_idle_time;
89         int threshold;
90         int threshold_max;
91         int threshold_min;
92         int cur_event;
93         bool on_boot;
94         bool app_exists;
95         bool touched;
96         int activation_method;
97         int deactivation_method;
98         unsigned int ttl;
99         guint live_timer;
100         int state;
101 } candidate_process_context_t;
102
103 typedef struct {
104         GPollFD *gpollfd;
105         int type;
106         int loader_id;
107 } loader_context_t;
108
109 typedef struct {
110         GQueue *queue;
111         guint timer;
112         guint idle_checker;
113         candidate_process_context_t *running_cpc;
114 } sequencer;
115
116 struct app_launch_arg {
117         const char *appid;
118         const char *app_path;
119         appinfo_t *menu_info;
120         bundle *kb;
121 };
122
123 struct app_arg {
124         int argc;
125         char **argv;
126 };
127
128 struct app_info {
129         const char *type;
130         bool exists;
131 };
132
133 static int __sys_hwacc;
134 static GList *loader_info_list;
135 static int user_slot_offset;
136 static GList *candidate_slot_list;
137 static app_labels_monitor *label_monitor;
138 static GList *launcher_info_list;
139 static GHashTable *__pid_table;
140 static int __memory_status;
141 static sequencer __sequencer;
142
143 static candidate_process_context_t *__add_slot(int type, int loader_id,
144                 int caller_pid, const char *loader_path, const char *extra,
145                 int detection_method, int activation_method,
146                 int deactivation_method, unsigned int ttl, int timeout_val,
147                 int threshold_max, int threshold_min, bool on_boot,
148                 bool app_exists);
149 static int __remove_slot(int type, int loader_id);
150 static int __add_default_slots(void);
151 static gboolean __handle_idle_checker(gpointer data);
152 static int __add_idle_checker(int detection_method, GList *cur);
153 static void __dispose_candidate_process(candidate_process_context_t *cpc);
154 static bool __is_low_memory(void);
155 static void __update_slot_state(candidate_process_context_t *cpc, int method);
156
157 static gboolean __handle_queuing_slots(gpointer data)
158 {
159         candidate_process_context_t *cpc;
160         unsigned long long total = 0;
161         unsigned long long idle = 0;
162
163         if (__sequencer.idle_checker > 0)
164                 return G_SOURCE_CONTINUE;
165
166         if (g_queue_is_empty(__sequencer.queue)) {
167                 __sequencer.timer = 0;
168                 return G_SOURCE_REMOVE;
169         }
170
171         cpc = (candidate_process_context_t *)g_queue_pop_head(
172                         __sequencer.queue);
173         if (!cpc) {
174                 _E("Critical error!");
175                 __sequencer.timer = 0;
176                 return G_SOURCE_REMOVE;;
177         }
178
179         if (!cpc->app_exists) {
180                 _W("The application is not installed. Type(%d)", cpc->type);
181                 return G_SOURCE_CONTINUE;
182         }
183
184         if (cpc->timer) {
185                 g_source_remove(cpc->timer);
186                 cpc->timer = 0;
187         }
188
189         if (cpc->pid != CANDIDATE_NONE) {
190                 _W("The slot(%d) is already running. pid(%d)",
191                                 cpc->type, cpc->pid);
192                 return G_SOURCE_CONTINUE;
193         }
194
195         _get_cpu_idle(&total, &idle);
196         cpc->cpu_idle_time = idle;
197         cpc->cpu_total_time = total;
198
199         __sequencer.idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
200                         __handle_idle_checker, cpc);
201         __sequencer.running_cpc = cpc;
202
203         _D("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type);
204
205         return G_SOURCE_CONTINUE;
206 }
207
208 static bool __sequencer_slot_is_running(candidate_process_context_t *cpc)
209 {
210         if (__sequencer.running_cpc == cpc)
211                 return true;
212
213         return false;
214 }
215
216 static bool __sequencer_slot_exist(candidate_process_context_t *cpc)
217 {
218         GList *found;
219
220         found = g_queue_find(__sequencer.queue, cpc);
221         if (found)
222                 return true;
223
224         return false;
225 }
226
227 static int __sequencer_add_slot(candidate_process_context_t *cpc)
228 {
229         if (__sequencer_slot_exist(cpc)) {
230                 _W("Already exists");
231                 return -1;
232         }
233
234         if (__sequencer_slot_is_running(cpc)) {
235                 _W("slot(%d) is running", cpc->type);
236                 return -1;
237         }
238
239         g_queue_push_tail(__sequencer.queue, cpc);
240
241         return 0;
242 }
243
244 static void __sequencer_remove_slot(candidate_process_context_t *cpc)
245 {
246         g_queue_remove(__sequencer.queue, cpc);
247 }
248
249 static void __sequencer_run(void)
250 {
251         if (__sequencer.timer)
252                 return;
253
254         __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, NULL);
255         if (!__sequencer.timer)
256                 _E("Failed to add sequencer timer");
257 }
258
259 static void __sequencer_stop(void)
260 {
261         if (!__sequencer.timer)
262                 return;
263
264         g_source_remove(__sequencer.timer);
265         __sequencer.timer = 0;
266 }
267
268 static bool __sequencer_queue_is_empty(void)
269 {
270         if (g_queue_is_empty(__sequencer.queue))
271                 return true;
272
273         return false;
274 }
275
276 static int __sequencer_init(void)
277 {
278         _D("[__SEQUENCER__] Init");
279
280         __sequencer.queue = g_queue_new();
281         if (!__sequencer.queue) {
282                 _E("Out of memory");
283                 return -1;
284         }
285
286         return 0;
287 }
288
289 static void __sequencer_fini(void)
290 {
291         _D("[__SEQUENCER__] Finish");
292
293         if (__sequencer.idle_checker > 0)
294                 g_source_remove(__sequencer.idle_checker);
295
296         if (__sequencer.timer > 0)
297                 g_source_remove(__sequencer.timer);
298
299         g_queue_free(__sequencer.queue);
300 }
301
302 static int __make_loader_id(void)
303 {
304         static int id = PAD_LOADER_ID_DYNAMIC_BASE;
305
306         return ++id;
307 }
308
309 static candidate_process_context_t *__find_slot_from_static_type(int type)
310 {
311         candidate_process_context_t *cpc;
312         GList *iter = candidate_slot_list;
313
314         if (type == LAUNCHPAD_TYPE_DYNAMIC ||
315                         type == LAUNCHPAD_TYPE_UNSUPPORTED)
316                 return NULL;
317
318         while (iter) {
319                 cpc = (candidate_process_context_t *)iter->data;
320                 if (type == cpc->type)
321                         return cpc;
322
323                 iter = g_list_next(iter);
324         }
325
326         return NULL;
327 }
328
329 static candidate_process_context_t *__find_slot_from_pid(int pid)
330 {
331         candidate_process_context_t *cpc;
332         GList *iter = candidate_slot_list;
333
334         while (iter) {
335                 cpc = (candidate_process_context_t *)iter->data;
336                 if (pid == cpc->pid)
337                         return cpc;
338
339                 iter = g_list_next(iter);
340         }
341
342         return NULL;
343 }
344
345 static candidate_process_context_t *__find_slot_from_caller_pid(int caller_pid)
346 {
347         candidate_process_context_t *cpc;
348         GList *iter = candidate_slot_list;
349
350         while (iter) {
351                 cpc = (candidate_process_context_t *)iter->data;
352                 if (caller_pid == cpc->caller_pid)
353                         return cpc;
354
355                 iter = g_list_next(iter);
356         }
357
358         return NULL;
359 }
360
361 static candidate_process_context_t *__find_slot_from_loader_id(int id)
362 {
363         candidate_process_context_t *cpc;
364         GList *iter = candidate_slot_list;
365
366         while (iter) {
367                 cpc = (candidate_process_context_t *)iter->data;
368                 if (id == cpc->loader_id)
369                         return cpc;
370
371                 iter = g_list_next(iter);
372         }
373
374         return NULL;
375 }
376
377 static candidate_process_context_t *__find_slot(int type, int loader_id)
378 {
379         if (type == LAUNCHPAD_TYPE_DYNAMIC)
380                 return __find_slot_from_loader_id(loader_id);
381
382         return __find_slot_from_static_type(type);
383 }
384
385 static void __kill_process(int pid)
386 {
387         char err_str[MAX_LOCAL_BUFSZ] = { 0, };
388
389         if (kill(pid, SIGKILL) == -1) {
390                 _E("send SIGKILL: %s",
391                                 strerror_r(errno, err_str, sizeof(err_str)));
392         }
393 }
394
395 static void __refuse_candidate_process(int server_fd)
396 {
397         int client_fd = -1;
398
399         if (server_fd == -1) {
400                 _E("arguments error!");
401                 goto error;
402         }
403
404         client_fd = accept(server_fd, NULL, NULL);
405         if (client_fd == -1) {
406                 _E("accept error!");
407                 goto error;
408         }
409
410         close(client_fd);
411         _D("refuse connection!");
412
413 error:
414         return;
415 }
416
417 static int __accept_candidate_process(int server_fd, int *out_client_fd,
418                 int *out_client_pid)
419 {
420         int client_fd = -1;
421         int client_pid = 0;
422         int recv_ret = 0;
423
424         if (server_fd == -1 || out_client_fd == NULL ||
425                         out_client_pid == NULL) {
426                 _E("arguments error!");
427                 goto error;
428         }
429
430         client_fd = accept(server_fd, NULL, NULL);
431         if (client_fd == -1) {
432                 _E("accept error!");
433                 goto error;
434         }
435
436         if (_set_sock_option(client_fd, 1) < 0) {
437                 _E("Failed to set sock option");
438                 goto error;
439         }
440
441         recv_ret = recv(client_fd, &client_pid, sizeof(client_pid),
442                         MSG_WAITALL);
443         if (recv_ret == -1) {
444                 _E("recv error!");
445                 goto error;
446         }
447
448         *out_client_fd = client_fd;
449         *out_client_pid = client_pid;
450
451         return *out_client_fd;
452
453 error:
454         if (client_fd != -1)
455                 close(client_fd);
456
457         return -1;
458 }
459
460 static int __listen_candidate_process(int type, int loader_id)
461 {
462         struct sockaddr_un addr;
463         int fd = -1;
464
465         _D("[launchpad] enter, type: %d", type);
466
467         memset(&addr, 0x00, sizeof(struct sockaddr_un));
468         addr.sun_family = AF_UNIX;
469         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d",
470                         SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
471                         type, loader_id);
472
473         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
474         if (fd < 0) {
475                 _E("Socket error");
476                 goto error;
477         }
478
479         unlink(addr.sun_path);
480
481         _D("bind to %s", addr.sun_path);
482         if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
483                 _E("bind error");
484                 goto error;
485         }
486
487         _D("listen to %s", addr.sun_path);
488         if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
489                 _E("listen error");
490                 goto error;
491         }
492
493         SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
494         return fd;
495
496 error:
497         if (fd != -1)
498                 close(fd);
499
500         return -1;
501 }
502
503 static int __get_loader_id(bundle *kb)
504 {
505         const char *val;
506
507         val = bundle_get_val(kb, AUL_K_LOADER_ID);
508         if (val == NULL)
509                 return -1;
510         _W("Requested loader id: %s", val);
511
512         return atoi(val);
513 }
514
515 static int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt)
516 {
517         return _send_pkt_raw(candidate_fd, pkt);
518 }
519
520 static int __real_send(int clifd, int ret)
521 {
522         if (clifd < 3) {
523                 _E("Invalid parameter. clifd(%d)", clifd);
524                 return -1;
525         }
526
527         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
528                 if (errno == EPIPE) {
529                         _E("send failed due to EPIPE.");
530                         close(clifd);
531                         return -1;
532                 }
533                 _E("send fail to client");
534         }
535
536         close(clifd);
537         return 0;
538 }
539
540 static void __send_result_to_caller(int clifd, int ret, const char *app_path)
541 {
542         _W("send result: %d", ret);
543
544         if (clifd == -1)
545                 return;
546
547         if (ret <= 1) {
548                 _E("launching failed");
549                 __real_send(clifd, ret);
550                 return;
551         }
552
553         if (__real_send(clifd, ret) < 0)
554                 __kill_process(ret);
555 }
556
557 static int __fork_app_process(int (*child_fn)(void *), void *arg)
558 {
559         int pid;
560         int ret;
561
562         pid = fork();
563
564         if (pid == -1) {
565                 _E("failed to fork child process");
566                 return -1;
567         }
568
569         if (pid == 0) {
570                 ret = child_fn(arg);
571                 _E("failed to exec app process (%d)", errno);
572                 exit(ret);
573         }
574
575         return pid;
576 }
577
578 static int __exec_loader_process(void *arg)
579 {
580         char **argv = arg;
581         char err_buf[1024];
582
583         _signal_unblock_sigchld();
584         _close_all_fds();
585         _setup_stdio(basename(argv[LOADER_ARG_PATH]));
586
587         if (execv(argv[LOADER_ARG_PATH], argv) < 0) {
588                 _send_message_to_logger(argv[LOADER_ARG_PATH],
589                         "Failed to prepare candidate process. error(%d:%s)",
590                         errno, strerror_r(errno, err_buf, sizeof(err_buf)));
591         } else {
592                 _D("Succeeded to prepare candidate_process");
593         }
594
595         return -1;
596 }
597
598 static gboolean __handle_deactivate_event(gpointer user_data)
599 {
600         candidate_process_context_t *cpc;
601
602         cpc = (candidate_process_context_t *)user_data;
603         __update_slot_state(cpc, METHOD_TTL);
604         _D("Deactivate event: type(%d)", cpc->type);
605
606         return G_SOURCE_REMOVE;
607 }
608
609 static void __set_live_timer(candidate_process_context_t *cpc)
610 {
611         if (!cpc)
612                 return;
613
614         if (cpc->deactivation_method & METHOD_TTL) {
615                 if (cpc->live_timer == 0) {
616                         cpc->live_timer = g_timeout_add_seconds(cpc->ttl,
617                                         __handle_deactivate_event, cpc);
618                 }
619         }
620 }
621
622 static int __prepare_candidate_process(int type, int loader_id)
623 {
624         int pid;
625         char type_str[2] = {0, };
626         char loader_id_str[10] = {0, };
627         char argbuf[LOADER_ARG_LEN];
628         char *argv[] = {NULL, NULL, NULL, NULL, NULL, NULL};
629         candidate_process_context_t *cpt = __find_slot(type, loader_id);
630
631         if (cpt == NULL)
632                 return -1;
633
634         _D("prepare candidate process / type:%d", type);
635         memset(argbuf, ' ', LOADER_ARG_LEN);
636         argbuf[LOADER_ARG_LEN - 1] = '\0';
637         argv[LOADER_ARG_DUMMY] = argbuf;
638
639         cpt->last_exec_time = time(NULL);
640
641         type_str[0] = '0' + type;
642         snprintf(loader_id_str, sizeof(loader_id_str), "%d", loader_id);
643         argv[LOADER_ARG_PATH] = cpt->loader_path;
644         argv[LOADER_ARG_TYPE] = type_str;
645         argv[LOADER_ARG_ID] = loader_id_str;
646         argv[LOADER_ARG_EXTRA] = cpt->loader_extra;
647
648         pid = __fork_app_process(__exec_loader_process, argv);
649         if (pid == -1) {
650                 _E("Failed to fork candidate_process");
651                 return -1;
652         }
653
654         cpt->pid = pid;
655         __set_live_timer(cpt);
656
657         return 0;
658 }
659
660 static gboolean __handle_timeout_event(gpointer user_data)
661 {
662         candidate_process_context_t *cpc;
663
664         cpc = (candidate_process_context_t *)user_data;
665         cpc->timer = 0;
666
667         if (cpc->pid != CANDIDATE_NONE) {
668                 _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid);
669                 return G_SOURCE_REMOVE;
670         }
671
672         __sequencer_add_slot(cpc);
673         __sequencer_run();
674         return G_SOURCE_REMOVE;
675 }
676
677 static void __set_timer(candidate_process_context_t *cpc)
678 {
679         if (cpc == NULL || cpc->timer > 0)
680                 return;
681
682         if ((cpc->detection_method & METHOD_TIMEOUT) &&
683                         cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) {
684                 cpc->timer = g_timeout_add(cpc->timeout_val,
685                                 __handle_timeout_event, cpc);
686         }
687 }
688
689 static void __reset_slot(candidate_process_context_t *cpc)
690 {
691         if (cpc == NULL)
692                 return;
693
694         cpc->send_fd = -1;
695         cpc->prepared = false;
696         cpc->pid = CANDIDATE_NONE;
697         cpc->source = 0;
698         cpc->timer = 0;
699         cpc->live_timer = 0;
700 }
701
702 static void __dispose_candidate_process(candidate_process_context_t *cpc)
703 {
704         if (!cpc)
705                 return;
706
707         _D("Dispose candidate process %d", cpc->type);
708         if (cpc->pid > 0) {
709                 _D("kill process %d", cpc->pid);
710                 __kill_process(cpc->pid);
711         }
712         if (cpc->live_timer > 0)
713                 g_source_remove(cpc->live_timer);
714         if (cpc->source > 0)
715                 g_source_remove(cpc->source);
716         if (cpc->timer > 0)
717                 g_source_remove(cpc->timer);
718         if (cpc->send_fd > 0)
719                 close(cpc->send_fd);
720         __reset_slot(cpc);
721 }
722
723 static int __send_launchpad_loader(candidate_process_context_t *cpc,
724                 app_pkt_t *pkt, const char *app_path, int clifd)
725 {
726         int pid = -1;
727         int ret;
728
729         ret = _delete_sock_path(cpc->pid, getuid());
730         if (ret != 0)
731                 return -1;
732
733         __candidate_process_real_launch(cpc->send_fd, pkt);
734         SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s",
735                 cpc->pid, app_path);
736
737         pid = cpc->pid;
738         cpc->pid = CANDIDATE_NONE;
739         __dispose_candidate_process(cpc);
740         __set_timer(cpc);
741         return pid;
742 }
743
744 static int __normal_fork_exec(int argc, char **argv, const char *app_path)
745 {
746         char *libdir;
747         char err_buf[1024];
748
749         _D("start real fork and exec");
750
751         libdir = _get_libdir(app_path);
752         if (libdir) {
753                 setenv("LD_LIBRARY_PATH", libdir, 1);
754                 free(libdir);
755         }
756
757         _close_all_fds();
758
759         if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */
760                 _send_message_to_logger(argv[LOADER_ARG_PATH],
761                         "Failed to execute a file. error(%d:%s)",
762                         errno, strerror_r(errno, err_buf, sizeof(err_buf)));
763                 return -1;
764         }
765         /* never reach*/
766         return 0;
767 }
768
769 static int __create_launcher_argv(int *argc, char ***argv, const char *app_type)
770 {
771         int launcher_argc;
772         char **launcher_argv;
773         launcher_info_h launcher_info;
774         const char *exe;
775         const char *extra_arg;
776         GList *extra_args;
777         GList *iter;
778         int i;
779
780         launcher_info = _launcher_info_find(launcher_info_list, app_type);
781         if (launcher_info == NULL)
782                 return 0;
783
784         exe = _launcher_info_get_exe(launcher_info);
785         if (exe == NULL) {
786                 _E("Failed to get launcher exe");
787                 return -1;
788         }
789
790         extra_args = _launcher_info_get_extra_args(launcher_info);
791         launcher_argc = g_list_length(extra_args) + 1;
792         launcher_argv = (char **)calloc(launcher_argc, sizeof(char *));
793         if (launcher_argv == NULL) {
794                 _E("out of memory");
795                 return -1;
796         }
797
798         i = LOADER_ARG_PATH;
799         launcher_argv[i++] = strdup(exe);
800
801         iter = g_list_first(extra_args);
802         while (iter) {
803                 extra_arg = (const char *)iter->data;
804                 if (extra_arg)
805                         launcher_argv[i++] = strdup(extra_arg);
806
807                 iter = g_list_next(iter);
808         }
809
810         *argc = launcher_argc;
811         *argv = launcher_argv;
812
813
814         return 0;
815 }
816
817 static void __destroy_launcher_argv(int argc, char **argv)
818 {
819         int i;
820
821         if (argv == NULL)
822                 return;
823
824         for (i = 0; i < argc; i++)
825                 free(argv[i]);
826         free(argv);
827 }
828
829 static int __create_app_argv(int *argc, char ***argv, const char *app_path,
830                 bundle *kb, const char *app_type)
831 {
832         int new_argc;
833         char **new_argv;
834         bool attach = false;
835         struct app_arg debug_arg = {0,};
836         struct app_arg launcher_arg = {0,};
837         struct app_arg arg = {0,};
838         struct app_arg debug_extra_arg = {0,};
839         int ret;
840         int i;
841         int c;
842
843         ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
844         if (ret < 0) {
845                 _E("Failed to create debugger argv");
846                 return -1;
847         }
848
849         if (attach) {
850                 *argc = debug_arg.argc;
851                 *argv = debug_arg.argv;
852                 return 0;
853         }
854
855         ret = _debug_create_extra_argv(&debug_extra_arg.argc,
856                         &debug_extra_arg.argv);
857         if (ret < 0) {
858                 _E("Failed to create debugger extra argv");
859                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
860                 return -1;
861         }
862
863         ret = __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv,
864                         app_type);
865         if (ret < 0) {
866                 _E("Failed to create launcher argv");
867                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
868                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
869                 return -1;
870         }
871
872         arg.argc = bundle_export_to_argv(kb, &arg.argv);
873         if (arg.argc <= 0) {
874                 _E("Failed to export bundle");
875                 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
876                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
877                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
878                 return -1;
879         }
880         arg.argv[LOADER_ARG_PATH] = strdup(app_path);
881
882         new_argc = debug_arg.argc + launcher_arg.argc + arg.argc +
883                 debug_extra_arg.argc;
884         if (new_argc == arg.argc) {
885                 *argc = arg.argc;
886                 *argv = arg.argv;
887                 return 0;
888         }
889
890         new_argv = (char **)calloc(new_argc + 1, sizeof(char *));
891         if (new_argv == NULL) {
892                 _E("out of memory");
893                 free(arg.argv[LOADER_ARG_PATH]);
894                 bundle_free_exported_argv(arg.argc, &arg.argv);
895                 __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
896                 _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
897                 _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
898                 return -1;
899         }
900
901         c = LOADER_ARG_PATH;
902         for (i = 0; i < debug_arg.argc; i++)
903                 new_argv[c++] = debug_arg.argv[i];
904         for (i = 0; i < launcher_arg.argc; i++)
905                 new_argv[c++] = launcher_arg.argv[i];
906         for (i = 0; i < arg.argc; i++)
907                 new_argv[c++] = arg.argv[i];
908         for (i = 0; i < debug_extra_arg.argc; i++)
909                 new_argv[c++] = debug_extra_arg.argv[i];
910
911         *argc = new_argc;
912         *argv = new_argv;
913
914         return 0;
915 }
916
917 static void __real_launch(const char *app_path, bundle *kb,
918                 appinfo_t *menu_info)
919 {
920         int app_argc = 0;
921         char **app_argv;
922         int i;
923         int ret;
924
925         if (bundle_get_val(kb, AUL_K_DEBUG) != NULL)
926                 putenv("TIZEN_DEBUGGING_PORT=1");
927
928         ret = __create_app_argv(&app_argc, &app_argv, app_path,
929                         kb, menu_info->app_type);
930         if (ret < 0) {
931                 _E("Failed to create app argv");
932                 exit(-1);
933         }
934
935         for (i = 0; i < app_argc; i++)
936                 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
937
938         PERF("setup argument done");
939         __normal_fork_exec(app_argc, app_argv, app_path);
940 }
941
942 static int __prepare_exec(const char *appid, const char *app_path,
943                         appinfo_t *menu_info, bundle *kb)
944 {
945         char *file_name;
946         char process_name[AUL_PR_NAME];
947         int ret;
948
949         /* Set new session ID & new process group ID*/
950         /* In linux, child can set new session ID without check permission */
951         /* TODO : should be add to check permission in the kernel*/
952         setsid();
953
954         ret = _enable_external_pkg(kb, menu_info->pkgid,
955                         menu_info->global ? GLOBAL_USER : getuid());
956         if (ret < 0)
957                 return PAD_ERR_FAILED;
958
959         if (menu_info->global)
960                 ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER);
961         else
962                 ret = trust_anchor_launch(menu_info->pkgid, getuid());
963         if (ret != TRUST_ANCHOR_ERROR_NONE &&
964                         ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
965                 _E("trust_anchor_launch() returns %d", ret);
966                 return PAD_ERR_REJECTED;
967         }
968
969         /* SET PRIVILEGES*/
970         _W("security_manager_prepare_app ++");
971         ret = security_manager_prepare_app(appid);
972         _W("security_manager_prepare_app --");
973         if (ret != SECURITY_MANAGER_SUCCESS)
974                 return PAD_ERR_REJECTED;
975
976         _send_cmd_to_amd(APP_STARTUP_SIGNAL);
977         if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE)
978                 _setup_stdio(basename(app_path));
979
980         /* SET DUMPABLE - for coredump*/
981         prctl(PR_SET_DUMPABLE, 1);
982
983         /* SET PROCESS NAME*/
984         if (app_path == NULL)
985                 return PAD_ERR_INVALID_ARGUMENT;
986
987         file_name = strrchr(app_path, '/');
988         if (file_name == NULL)
989                 return PAD_ERR_INVALID_PATH;
990
991         file_name++;
992         if (*file_name == '\0')
993                 return PAD_ERR_INVALID_PATH;
994
995         memset(process_name, '\0', AUL_PR_NAME);
996         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
997         prctl(PR_SET_NAME, process_name);
998
999         /* SET ENVIROMENT*/
1000         _set_env(menu_info, kb);
1001
1002         ret = _wait_tep_mount(kb);
1003         if (ret < 0)
1004                 return PAD_ERR_FAILED;
1005
1006         if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) {
1007                 ret = _prepare_app_socket();
1008                 if (ret < 0)
1009                         return PAD_ERR_FAILED;
1010
1011                 ret = _prepare_id_file();
1012                 if (ret < 0)
1013                         return PAD_ERR_FAILED;
1014         }
1015
1016         return 0;
1017 }
1018
1019 static int __exec_app_process(void *arg)
1020 {
1021         struct app_launch_arg *launch_arg = arg;
1022         int ret;
1023
1024         PERF("fork done");
1025         _D("lock up test log(no error) : fork done");
1026
1027         if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1028                 _debug_prepare_debugger(launch_arg->kb);
1029
1030         _signal_unblock_sigchld();
1031
1032         _delete_sock_path(getpid(), getuid());
1033
1034         PERF("prepare exec - first done");
1035         ret = __prepare_exec(launch_arg->appid, launch_arg->app_path,
1036                         launch_arg->menu_info, launch_arg->kb);
1037         if (ret < 0)
1038                 return ret;
1039
1040         PERF("prepare exec - second done");
1041         __real_launch(launch_arg->app_path, launch_arg->kb,
1042                         launch_arg->menu_info);
1043
1044         return PAD_ERR_FAILED;
1045 }
1046
1047 static int __launch_directly(const char *appid, const char *app_path, int clifd,
1048                 bundle *kb, appinfo_t *menu_info,
1049                 candidate_process_context_t *cpc)
1050 {
1051         struct app_launch_arg arg;
1052         int pid;
1053
1054         arg.appid = appid;
1055         arg.app_path = app_path;
1056         arg.menu_info = menu_info;
1057         arg.kb = kb;
1058
1059         pid = __fork_app_process(__exec_app_process, &arg);
1060         if (pid <= 0)
1061                 _E("failed to fork app process");
1062
1063         SECURE_LOGD("==> real launch pid : %d %s", pid, app_path);
1064
1065         return pid;
1066 }
1067
1068 static int __create_sock_activation(void)
1069 {
1070         int fds;
1071
1072         fds = sd_listen_fds(0);
1073         if (fds == 1)
1074                 return SD_LISTEN_FDS_START;
1075         else if (fds > 1)
1076                 _E("Too many file descriptors received.");
1077         else
1078                 _D("There is no socket stream");
1079
1080         return -1;
1081 }
1082
1083 static int __launchpad_pre_init(int argc, char **argv)
1084 {
1085         int fd;
1086
1087         /* signal init*/
1088         _signal_init();
1089
1090         /* create launchpad sock */
1091         fd = __create_sock_activation();
1092         if (fd < 0) {
1093                 fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK);
1094                 if (fd < 0) {
1095                         _E("server sock error %d", fd);
1096                         return -1;
1097                 }
1098         }
1099
1100         return fd;
1101 }
1102
1103 static void __destroy_poll_data(gpointer data)
1104 {
1105         free(data);
1106 }
1107
1108 static gboolean __glib_check(GSource *src)
1109 {
1110         GSList *fd_list;
1111         GPollFD *tmp;
1112
1113         fd_list = src->poll_fds;
1114         do {
1115                 tmp = (GPollFD *) fd_list->data;
1116                 if ((tmp->revents & (G_IO_IN | G_IO_PRI | G_IO_HUP |
1117                                                 G_IO_NVAL)))
1118                         return TRUE;
1119                 fd_list = fd_list->next;
1120         } while (fd_list);
1121
1122         return FALSE;
1123 }
1124
1125 static gboolean __glib_dispatch(GSource *src, GSourceFunc callback,
1126                 gpointer data)
1127 {
1128         return callback(data);
1129 }
1130
1131 static gboolean __glib_prepare(GSource *src, gint *timeout)
1132 {
1133         return FALSE;
1134 }
1135
1136 static void __glib_finalize(GSource *src)
1137 {
1138         GSList *fd_list;
1139         GPollFD *gpollfd;
1140
1141         fd_list = src->poll_fds;
1142         do {
1143                 gpollfd = (GPollFD *)fd_list->data;
1144                 close(gpollfd->fd);
1145                 g_free(gpollfd);
1146
1147                 fd_list = fd_list->next;
1148         } while (fd_list);
1149 }
1150
1151 static GSourceFuncs funcs = {
1152         .prepare = __glib_prepare,
1153         .check = __glib_check,
1154         .dispatch = __glib_dispatch,
1155         .finalize = __glib_finalize
1156 };
1157
1158 static guint __poll_fd(int fd, gushort events, GSourceFunc func, int type,
1159                 int loader_id)
1160 {
1161         int r;
1162         GPollFD *gpollfd;
1163         GSource *src;
1164         loader_context_t *lc;
1165
1166         src = g_source_new(&funcs, sizeof(GSource));
1167         if (!src) {
1168                 _E("out of memory");
1169                 return 0;
1170         }
1171
1172         gpollfd = (GPollFD *)g_malloc(sizeof(GPollFD));
1173         if (!gpollfd) {
1174                 _E("out of memory");
1175                 g_source_destroy(src);
1176                 return 0;
1177         }
1178
1179         gpollfd->events = events;
1180         gpollfd->fd = fd;
1181
1182         lc = malloc(sizeof(loader_context_t));
1183         if (lc == NULL) {
1184                 g_free(gpollfd);
1185                 g_source_destroy(src);
1186                 return 0;
1187         }
1188
1189         lc->gpollfd = gpollfd;
1190         lc->type = type;
1191         lc->loader_id = loader_id;
1192
1193         g_source_add_poll(src, gpollfd);
1194         g_source_set_callback(src, func,
1195                         (gpointer) lc, __destroy_poll_data);
1196         g_source_set_priority(src, G_PRIORITY_DEFAULT);
1197
1198         r = g_source_attach(src, NULL);
1199         if (r  == 0) {
1200                 g_free(gpollfd);
1201                 g_source_destroy(src);
1202                 return 0;
1203         }
1204
1205         return r;
1206 }
1207
1208 static gboolean __handle_loader_client_event(gpointer data)
1209 {
1210         loader_context_t *lc = (loader_context_t *) data;
1211         int type = lc->type;
1212         int loader_id = lc->loader_id;
1213         gushort revents = lc->gpollfd->revents;
1214         candidate_process_context_t *cpc = __find_slot(type, loader_id);
1215
1216         if (cpc == NULL)
1217                 return G_SOURCE_REMOVE;
1218
1219         if (revents & (G_IO_HUP | G_IO_NVAL)) {
1220                 SECURE_LOGE("Type %d candidate process was " \
1221                                 "(POLLHUP|POLLNVAL), pid: %d",
1222                                 cpc->type, cpc->pid);
1223                 cpc->pid = CANDIDATE_NONE;
1224                 __dispose_candidate_process(cpc);
1225                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1226                 return G_SOURCE_REMOVE;
1227         }
1228
1229         return G_SOURCE_CONTINUE;
1230 }
1231
1232 static gboolean __handle_loader_event(gpointer data)
1233 {
1234         loader_context_t *lc = (loader_context_t *) data;
1235         int fd = lc->gpollfd->fd;
1236         int type = lc->type;
1237         int loader_id = lc->loader_id;
1238         int client_fd;
1239         int client_pid;
1240         int ret;
1241
1242         candidate_process_context_t *cpc = __find_slot(type, loader_id);
1243
1244         if (cpc == NULL)
1245                 return G_SOURCE_REMOVE;
1246
1247         if (!cpc->prepared) {
1248                 ret = __accept_candidate_process(fd, &client_fd, &client_pid);
1249                 if (ret >= 0) {
1250                         cpc->prepared = true;
1251                         cpc->send_fd = client_fd;
1252
1253                         SECURE_LOGD("Type %d candidate process was connected," \
1254                                         " pid: %d", type, cpc->pid);
1255                         cpc->source = __poll_fd(client_fd, G_IO_IN | G_IO_HUP,
1256                                         __handle_loader_client_event, type,
1257                                         loader_id);
1258                         if (cpc->source == 0)
1259                                 close(client_fd);
1260                 }
1261         } else {
1262                 __refuse_candidate_process(fd);
1263                 _E("Refused candidate process connection");
1264         }
1265
1266         return G_SOURCE_CONTINUE;
1267 }
1268
1269 static gboolean __handle_sigchild(gpointer data)
1270 {
1271         candidate_process_context_t *cpc;
1272         loader_context_t *lc = (loader_context_t *) data;
1273         int fd = lc->gpollfd->fd;
1274         struct signalfd_siginfo siginfo;
1275         ssize_t s;
1276         char *appid;
1277
1278         do {
1279                 s = read(fd, &siginfo, sizeof(struct signalfd_siginfo));
1280                 if (s == 0)
1281                         break;
1282
1283                 if (s != sizeof(struct signalfd_siginfo))
1284                         break;
1285
1286                 _signal_process_sigchld(&siginfo);
1287
1288                 appid = g_hash_table_lookup(__pid_table,
1289                                 GINT_TO_POINTER(siginfo.ssi_pid));
1290                 if (appid) {
1291                         security_manager_cleanup_app(appid, siginfo.ssi_uid, siginfo.ssi_pid);
1292                         g_hash_table_remove(__pid_table,
1293                                         GINT_TO_POINTER(siginfo.ssi_pid));
1294                 }
1295
1296                 cpc = __find_slot_from_pid(siginfo.ssi_pid);
1297                 if (cpc != NULL) {
1298                         cpc->pid = CANDIDATE_NONE;
1299                         __dispose_candidate_process(cpc);
1300                         __prepare_candidate_process(cpc->type, cpc->loader_id);
1301                 }
1302
1303                 cpc = __find_slot_from_caller_pid(siginfo.ssi_pid);
1304                 while (cpc) {
1305                         __remove_slot(LAUNCHPAD_TYPE_DYNAMIC, cpc->loader_id);
1306                         cpc = __find_slot_from_caller_pid(siginfo.ssi_pid);
1307                 }
1308         } while (s > 0);
1309
1310         return G_SOURCE_CONTINUE;
1311 }
1312
1313 static gboolean __handle_label_monitor(gpointer data)
1314 {
1315         candidate_process_context_t *cpc;
1316         GList *iter = candidate_slot_list;
1317
1318         _D("__handle_label_monitor()");
1319         security_manager_app_labels_monitor_process(label_monitor);
1320
1321         while (iter) {
1322                 cpc = (candidate_process_context_t *)iter->data;
1323                 if (cpc->pid > 0) {
1324                         __dispose_candidate_process(cpc);
1325                         __prepare_candidate_process(cpc->type, cpc->loader_id);
1326                 }
1327
1328                 iter = g_list_next(iter);
1329         }
1330
1331         return G_SOURCE_CONTINUE;
1332 }
1333
1334 static float __interpolator(float input, int cpu_max, int cpu_min)
1335 {
1336         float ret;
1337         float min = cpu_min / 100.0f;
1338         float max = cpu_max / 100.0f;
1339
1340         if (input > 1.0f)
1341                 input = 1.0f;
1342         if (input < 0.0f)
1343                 input = 0.0f;
1344
1345         ret = cos(input * PI) / 2.0f + 0.5f;
1346         ret *= max - min;
1347         ret += min;
1348
1349         return ret;
1350 }
1351
1352 static void __update_threshold(candidate_process_context_t *cpc, float delta)
1353 {
1354         static float pos = 0.0f;
1355
1356         pos += delta;
1357         if (pos < 0.0f)
1358                 pos = 0.0f;
1359
1360         if (pos > 1.0f)
1361                 pos = 1.0f;
1362
1363         cpc->threshold = (int)(__interpolator(pos,
1364                                 cpc->threshold_max, cpc->threshold_min) * 100);
1365         _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d",
1366                         cpc->type, delta, pos, cpc->threshold);
1367 }
1368
1369 static gboolean __handle_idle_checker(gpointer data)
1370 {
1371         unsigned long long total = 0;
1372         unsigned long long idle = 0;
1373         int per;
1374         candidate_process_context_t *cpc;
1375
1376         if (!data) {
1377                 _E("Critical error!");
1378                 __sequencer.idle_checker = 0;
1379                 __sequencer.running_cpc = NULL;
1380                 return G_SOURCE_REMOVE;
1381         }
1382
1383         cpc = (candidate_process_context_t *)data;
1384         if (!cpc->app_exists) {
1385                 _W("The application is not installed. Type(%d)", cpc->type);
1386                 __sequencer.idle_checker = 0;
1387                 __sequencer.running_cpc = NULL;
1388                 return G_SOURCE_REMOVE;
1389         }
1390
1391         if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1392                 _W("Slot state is not running. Type(%d)", cpc->type);
1393                 __sequencer.idle_checker = 0;
1394                 __sequencer.running_cpc = NULL;
1395                 return G_SOURCE_REMOVE;
1396         }
1397
1398         _get_cpu_idle(&total, &idle);
1399         if (total == cpc->cpu_total_time)
1400                 total++;
1401
1402         per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time);
1403         _D("[CPU] Idle : %d / type : %d", per, cpc->type);
1404
1405         if (per >= cpc->threshold) {
1406                 __update_threshold(cpc, -0.02f * (per - cpc->threshold));
1407                 __prepare_candidate_process(cpc->type, cpc->loader_id);
1408                 cpc->touched = true;
1409                 __sequencer.idle_checker = 0;
1410                 __sequencer.running_cpc = NULL;
1411                 return G_SOURCE_REMOVE;
1412         }
1413
1414         cpc->cpu_idle_time = idle;
1415         cpc->cpu_total_time = total;
1416         __update_threshold(cpc, 0.05f);
1417
1418         return G_SOURCE_CONTINUE;
1419 }
1420
1421 static int __add_idle_checker(int detection_method, GList *cur)
1422 {
1423         candidate_process_context_t *cpc;
1424         GList *iter = cur;
1425
1426         while (iter) {
1427                 cpc = (candidate_process_context_t *)iter->data;
1428                 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
1429                         iter = g_list_next(iter);
1430                         continue;
1431                 }
1432
1433                 if (strcmp("null", cpc->loader_path) == 0) {
1434                         iter = g_list_next(iter);
1435                         continue;
1436                 }
1437
1438                 if (!cpc->touched && !cpc->on_boot) {
1439                         iter = g_list_next(iter);
1440                         continue;
1441                 }
1442
1443                 if (!cpc->app_exists) {
1444                         iter = g_list_next(iter);
1445                         continue;
1446                 }
1447
1448                 if (cpc->pid == CANDIDATE_NONE &&
1449                                 (!cpc->touched ||
1450                                  (cpc->detection_method & detection_method))) {
1451                         if (cpc->timer > 0) {
1452                                 g_source_remove(cpc->timer);
1453                                 cpc->timer = 0;
1454                         }
1455
1456                         cpc->cur_event = detection_method;
1457                         __sequencer_add_slot(cpc);
1458                         __sequencer_run();
1459                 }
1460
1461                 iter = g_list_next(iter);
1462         }
1463
1464         return -1;
1465 }
1466
1467 static int __dispatch_cmd_hint(bundle *kb, int detection_method)
1468 {
1469         _W("cmd hint %d", detection_method);
1470         __add_idle_checker(detection_method, candidate_slot_list);
1471
1472         return 0;
1473 }
1474
1475 static int __dispatch_cmd_add_loader(bundle *kb)
1476 {
1477         const char *add_slot_str = NULL;
1478         const char *caller_pid = NULL;
1479         const char *extra;
1480         int lid;
1481         candidate_process_context_t *cpc;
1482
1483         _W("cmd add loader");
1484         add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH);
1485         caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
1486         extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA);
1487
1488         if (add_slot_str && caller_pid) {
1489                 lid = __make_loader_id();
1490                 cpc = __add_slot(LAUNCHPAD_TYPE_DYNAMIC, lid, atoi(caller_pid),
1491                                 add_slot_str, extra,
1492                                 METHOD_TIMEOUT | METHOD_VISIBILITY,
1493                                 METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
1494                                 METHOD_TTL | METHOD_OUT_OF_MEMORY,
1495                                 600,
1496                                 2000,
1497                                 DEFAULT_CPU_THRESHOLD_MAX,
1498                                 DEFAULT_CPU_THRESHOLD_MIN,
1499                                 false,
1500                                 true);
1501                 __set_timer(cpc);
1502                 return lid;
1503         }
1504
1505         return -1;
1506 }
1507
1508 static int __dispatch_cmd_remove_loader(bundle *kb)
1509 {
1510         const char *id = bundle_get_val(kb, AUL_K_LOADER_ID);
1511         int lid;
1512
1513         _W("cmd remove loader");
1514         if (id) {
1515                 lid = atoi(id);
1516                 if (__remove_slot(LAUNCHPAD_TYPE_DYNAMIC, lid) == 0)
1517                         return 0;
1518         }
1519
1520         return -1;
1521 }
1522
1523 static int __check_caller_by_pid(int pid)
1524 {
1525         int ret;
1526         char buf[PATH_MAX] = { 0, };
1527
1528         ret = _proc_get_attr_by_pid(pid, buf, sizeof(buf));
1529         if (ret < 0)
1530                 return -1;
1531
1532         if (strcmp(buf, "User") == 0 ||
1533                         strcmp(buf, "System") == 0 ||
1534                         strcmp(buf, "System::Privileged") == 0)
1535                 return 0;
1536
1537         return -1;
1538 }
1539
1540 static bool __is_hw_acc(const char *hwacc)
1541 {
1542         if (strcmp(hwacc, "USE") == 0 ||
1543                 (strcmp(hwacc, "SYS") == 0 &&
1544                         __sys_hwacc == SETTING_HW_ACCELERATION_ON))
1545                 return true;
1546
1547         return false;
1548 }
1549
1550 static candidate_process_context_t *__find_available_slot(const char *hwacc,
1551                 const char *app_type, const char *loader_name,
1552                 candidate_process_context_t **org_cpc)
1553 {
1554         int type;
1555         candidate_process_context_t *cpc;
1556         int *a_types;
1557         int len = 0;
1558         int i;
1559
1560         if (loader_name) {
1561                 type = _loader_info_find_type_by_loader_name(loader_info_list,
1562                                 loader_name);
1563         } else {
1564                 type = _loader_info_find_type(loader_info_list,
1565                                 app_type, __is_hw_acc(hwacc));
1566         }
1567         cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1568         if (!cpc)
1569                 return NULL;
1570
1571         *org_cpc = cpc;
1572
1573         if (cpc->prepared)
1574                 return cpc;
1575
1576         a_types = _loader_get_alternative_types(loader_info_list, type, &len);
1577         if (!a_types)
1578                 return NULL;
1579
1580         for (i = 0; i < len; i++) {
1581                 cpc = __find_slot(a_types[i], PAD_LOADER_ID_STATIC);
1582                 if (!cpc)
1583                         continue;
1584                 if (cpc->prepared) {
1585                         free(a_types);
1586                         return cpc;
1587                 }
1588         }
1589
1590         free(a_types);
1591         return NULL;
1592 }
1593
1594 static void __update_slot(int type, bool app_exists)
1595 {
1596         candidate_process_context_t *cpc;
1597
1598         cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
1599         if (!cpc)
1600                 return;
1601
1602         cpc->app_exists = app_exists;
1603         if (!cpc->app_exists) {
1604                 if (cpc->pid > 0)
1605                         __dispose_candidate_process(cpc);
1606                 __sequencer_remove_slot(cpc);
1607                 if (__sequencer_queue_is_empty())
1608                         __sequencer_stop();
1609         } else {
1610                 if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
1611                         return;
1612
1613                 if (!cpc->touched && !cpc->on_boot)
1614                         return;
1615
1616                 if (cpc->timer > 0) {
1617                         g_source_remove(cpc->timer);
1618                         cpc->timer = 0;
1619                 }
1620
1621                 if (cpc->pid == CANDIDATE_NONE) {
1622                         __sequencer_add_slot(cpc);
1623                         __sequencer_run();
1624                 }
1625         }
1626 }
1627
1628 static void __foreach_loader_info(loader_info_t *info, void *data)
1629 {
1630         struct app_info *ai = (struct app_info *)data;
1631         bool exist;
1632
1633         exist = _loader_info_exist_app_type(info, ai->type);
1634         if (!exist)
1635                 return;
1636
1637         info->app_exists = ai->exists;
1638         __update_slot(info->type, info->app_exists);
1639 }
1640
1641 static int __dispatch_cmd_update_app_type(bundle *b)
1642 {
1643         int r;
1644         struct app_info info;
1645         const char *is_installed;
1646
1647         info.type = bundle_get_val(b, AUL_K_APP_TYPE);
1648         if (!info.type)
1649                 return -1;
1650
1651         is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED);
1652         if (is_installed && !strcmp(is_installed, "true"))
1653                 info.exists = true;
1654         else
1655                 info.exists = false;
1656
1657         _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists);
1658
1659         r = _loader_info_foreach(loader_info_list, __foreach_loader_info,
1660                         &info);
1661         if (r != 0) {
1662                 _E("Failed to retrieve loader info");
1663                 return -1;
1664         }
1665
1666         return 0;
1667 }
1668
1669 static void __update_slot_state(candidate_process_context_t *cpc, int method)
1670 {
1671         if (method == METHOD_OUT_OF_MEMORY) {
1672                 if ((cpc->deactivation_method & method) && __is_low_memory()) {
1673                         cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
1674                         __dispose_candidate_process(cpc);
1675                 } else {
1676                         cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
1677                         if (!cpc->touched && !cpc->on_boot)
1678                                 return;
1679                         if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE)
1680                                 return;
1681                         if (cpc->detection_method & METHOD_TIMEOUT)
1682                                 __set_timer(cpc);
1683                 }
1684         } else if (cpc->activation_method & method) {
1685                 __update_slot_state(cpc, METHOD_OUT_OF_MEMORY);
1686         } else if (cpc->deactivation_method & method) {
1687                 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
1688                 __dispose_candidate_process(cpc);
1689         } else {
1690                 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
1691                 if (!cpc->touched && !cpc->on_boot)
1692                         return;
1693                 if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE)
1694                         return;
1695                 if (cpc->detection_method & METHOD_TIMEOUT)
1696                         __set_timer(cpc);
1697         }
1698 }
1699
1700 static gboolean __handle_launch_event(gpointer data)
1701 {
1702         loader_context_t *lc = (loader_context_t *) data;
1703         int fd = lc->gpollfd->fd;
1704         bundle *kb = NULL;
1705         app_pkt_t *pkt = NULL;
1706         appinfo_t *menu_info = NULL;
1707         candidate_process_context_t *cpc = NULL;
1708         candidate_process_context_t *org_cpc = NULL;
1709         const char *app_path = NULL;
1710         int pid = -1;
1711         int clifd = -1;
1712         struct ucred cr;
1713         int type = -1;
1714         int loader_id;
1715         int ret;
1716
1717         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
1718         pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
1719         if (!pkt) {
1720                 _E("packet is NULL");
1721                 goto end;
1722         }
1723
1724         if (cr.uid >= REGULAR_UID_MIN) {
1725                 if (__check_caller_by_pid(cr.pid) < 0) {
1726                         _E("Invalid caller pid");
1727                         goto end;
1728                 }
1729         }
1730
1731         kb = bundle_decode(pkt->data, pkt->len);
1732         if (!kb) {
1733                 _E("bundle decode error");
1734                 goto end;
1735         }
1736
1737         if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
1738                 _debug_init();
1739
1740         switch (pkt->cmd) {
1741         case PAD_CMD_VISIBILITY:
1742                 ret = __dispatch_cmd_hint(kb, METHOD_VISIBILITY);
1743                 __real_send(clifd, ret);
1744                 clifd = -1;
1745                 goto end;
1746         case PAD_CMD_ADD_LOADER:
1747                 ret = __dispatch_cmd_add_loader(kb);
1748                 __real_send(clifd, ret);
1749                 clifd = -1;
1750                 goto end;
1751         case PAD_CMD_REMOVE_LOADER:
1752                 ret = __dispatch_cmd_remove_loader(kb);
1753                 __real_send(clifd, ret);
1754                 clifd = -1;
1755                 goto end;
1756         case PAD_CMD_MAKE_DEFAULT_SLOTS:
1757                 ret = __add_default_slots();
1758                 if (ret != 0)
1759                         _E("Failed to make default slots");
1760                 __real_send(clifd, ret);
1761                 clifd = -1;
1762                 goto end;
1763         case PAD_CMD_DEMAND:
1764                 ret = __dispatch_cmd_hint(kb, METHOD_DEMAND);
1765                 __real_send(clifd, ret);
1766                 clifd = -1;
1767                 goto end;
1768         case PAD_CMD_PING:
1769                 __real_send(clifd, getpid());
1770                 clifd = -1;
1771                 goto end;
1772         case PAD_CMD_UPDATE_APP_TYPE:
1773                 __dispatch_cmd_update_app_type(kb);
1774                 close(clifd);
1775                 clifd = -1;
1776                 goto end;
1777         }
1778
1779         INIT_PERF(kb);
1780         PERF("packet processing start");
1781
1782         menu_info = _appinfo_create(kb);
1783         if (menu_info == NULL) {
1784                 _E("such pkg no found");
1785                 goto end;
1786         }
1787
1788         app_path = _appinfo_get_app_path(menu_info);
1789         if (app_path == NULL) {
1790                 _E("app_path is NULL");
1791                 goto end;
1792         }
1793         if (app_path[0] != '/') {
1794                 _E("app_path is not absolute path");
1795                 goto end;
1796         }
1797
1798         if (menu_info->hwacc == NULL) {
1799                 _E("[launchpad] Failed to find H/W acceleration type");
1800                 goto end;
1801         }
1802
1803         SECURE_LOGD("exec : %s", menu_info->app_path);
1804         SECURE_LOGD("comp_type : %s", menu_info->comp_type);
1805         SECURE_LOGD("internal pool : %s", menu_info->internal_pool);
1806         SECURE_LOGD("hwacc : %s", menu_info->hwacc);
1807         SECURE_LOGD("app_type : %s", menu_info->app_type);
1808         SECURE_LOGD("pkg_type : %s", menu_info->pkg_type);
1809
1810         if (menu_info->comp_type &&
1811                         strcmp(menu_info->comp_type, "svcapp") == 0) {
1812                 loader_id = PAD_LOADER_ID_DIRECT;
1813         } else if (menu_info->comp_type && menu_info->app_type &&
1814                         strcmp(menu_info->comp_type, "widgetapp") == 0 &&
1815                         strcmp(menu_info->app_type, "webapp") == 0) {
1816                 loader_id = PAD_LOADER_ID_DIRECT;
1817         } else {
1818                 loader_id = __get_loader_id(kb);
1819                 if (loader_id <= PAD_LOADER_ID_STATIC) {
1820                         cpc = __find_available_slot(menu_info->hwacc,
1821                                         menu_info->app_type,
1822                                         menu_info->loader_name, &org_cpc);
1823                 } else {
1824                         type = LAUNCHPAD_TYPE_DYNAMIC;
1825                         cpc = __find_slot(type, loader_id);
1826                 }
1827         }
1828
1829         _modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
1830         if (menu_info->appid == NULL) {
1831                 _E("unable to get appid from menu_info");
1832                 goto end;
1833         }
1834
1835         PERF("get package information & modify bundle done");
1836
1837         if (loader_id == PAD_LOADER_ID_DIRECT || cpc == NULL) {
1838                 _W("Launch directly %d %p", loader_id, cpc);
1839                 pid = __launch_directly(menu_info->appid, app_path, clifd, kb,
1840                                 menu_info, NULL);
1841                 if (org_cpc && org_cpc->app_exists &&
1842                                 org_cpc->pid == CANDIDATE_NONE &&
1843                                 !__sequencer_slot_exist(org_cpc)) {
1844                         if (org_cpc->timer > 0) {
1845                                 g_source_remove(org_cpc->timer);
1846                                 org_cpc->timer = 0;
1847                         }
1848
1849                         __update_slot_state(org_cpc, METHOD_REQUEST);
1850                         __set_timer(org_cpc);
1851                 }
1852         } else {
1853                 _W("Launch %d type process", cpc->type);
1854                 pid = __send_launchpad_loader(cpc, pkt, app_path, clifd);
1855         }
1856
1857         __send_result_to_caller(clifd, pid, app_path);
1858         clifd = -1;
1859 end:
1860         if (clifd != -1)
1861                 close(clifd);
1862
1863         if (pid > 0) {
1864                 _signal_send_app_launch_signal(pid, menu_info->appid);
1865                 g_hash_table_insert(__pid_table, GINT_TO_POINTER(pid),
1866                                 strdup(menu_info->appid));
1867         }
1868
1869         if (menu_info != NULL)
1870                 _appinfo_free(menu_info);
1871
1872         if (kb != NULL)
1873                 bundle_free(kb);
1874         if (pkt != NULL)
1875                 free(pkt);
1876
1877         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1878
1879         return G_SOURCE_CONTINUE;
1880 }
1881
1882 static candidate_process_context_t *__add_slot(int type, int loader_id,
1883                 int caller_pid, const char *loader_path,
1884                 const char *loader_extra, int detection_method,
1885                 int activation_method, int deactivation_method,
1886                 unsigned int ttl, int timeout_val,
1887                 int threshold_max, int threshold_min,
1888                 bool on_boot, bool app_exists)
1889 {
1890         candidate_process_context_t *cpc;
1891         int fd = -1;
1892         guint pollfd;
1893
1894         if (__find_slot(type, loader_id) != NULL)
1895                 return NULL;
1896
1897         cpc = (candidate_process_context_t *)malloc(
1898                         sizeof(candidate_process_context_t));
1899         if (cpc == NULL)
1900                 return NULL;
1901
1902         cpc->type = type;
1903         cpc->prepared = false;
1904         cpc->pid = CANDIDATE_NONE;
1905         cpc->caller_pid = caller_pid;
1906         cpc->loader_id = loader_id;
1907         cpc->send_fd = -1;
1908         cpc->last_exec_time = 0;
1909         cpc->source = 0;
1910         cpc->timer = 0;
1911         cpc->loader_path = strdup(loader_path);
1912         cpc->loader_extra = loader_extra ? strdup(loader_extra) : strdup("");
1913         cpc->detection_method = detection_method;
1914         cpc->timeout_val = timeout_val;
1915         cpc->cpu_total_time = 0;
1916         cpc->cpu_idle_time = 0;
1917         cpc->threshold = threshold_max;
1918         cpc->threshold_max = threshold_max;
1919         cpc->threshold_min = threshold_min;
1920         cpc->on_boot = on_boot;
1921         cpc->app_exists = app_exists;
1922         cpc->touched = false;
1923         cpc->cur_event = 0;
1924         cpc->activation_method = activation_method;
1925         cpc->deactivation_method = deactivation_method;
1926         cpc->ttl = ttl;
1927         cpc->live_timer = 0;
1928
1929         if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) &&
1930                         __is_low_memory())
1931                 cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
1932         else
1933                 cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
1934
1935         fd = __listen_candidate_process(cpc->type, cpc->loader_id);
1936         if (fd == -1) {
1937                 _E("[launchpad] Listening the socket to " \
1938                                 "the type %d candidate process failed.",
1939                                 cpc->type);
1940                 free(cpc);
1941                 return NULL;
1942         }
1943
1944         pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_loader_event,
1945                         cpc->type, cpc->loader_id);
1946         if (pollfd == 0) {
1947                 close(fd);
1948                 free(cpc);
1949                 return NULL;
1950         }
1951
1952         candidate_slot_list = g_list_append(candidate_slot_list, cpc);
1953
1954         return cpc;
1955 }
1956
1957 static int __remove_slot(int type, int loader_id)
1958 {
1959         candidate_process_context_t *cpc;
1960         GList *iter;
1961
1962         iter = candidate_slot_list;
1963         while (iter) {
1964                 cpc = (candidate_process_context_t *)iter->data;
1965                 if (type == cpc->type && loader_id == cpc->loader_id) {
1966                         __dispose_candidate_process(cpc);
1967                         candidate_slot_list = g_list_delete_link(
1968                                         candidate_slot_list, iter);
1969                         free(cpc->loader_path);
1970                         if (cpc->loader_extra)
1971                                 free(cpc->loader_extra);
1972
1973                         free(cpc);
1974                         return 0;
1975                 }
1976
1977                 iter = g_list_next(iter);
1978         }
1979
1980         return -1;
1981 }
1982
1983 static int __init_launchpad_fd(int argc, char **argv)
1984 {
1985         int fd = -1;
1986         guint pollfd;
1987
1988         fd = __launchpad_pre_init(argc, argv);
1989         if (fd < 0) {
1990                 _E("launchpad pre init failed");
1991                 return -1;
1992         }
1993
1994         pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_launch_event, 0,
1995                         0);
1996         if (pollfd == 0) {
1997                 close(fd);
1998                 return -1;
1999         }
2000
2001         return 0;
2002 }
2003
2004 static int __init_sigchild_fd(void)
2005 {
2006         int fd = -1;
2007         guint pollfd;
2008
2009         fd = _signal_get_sigchld_fd();
2010         if (fd < 0) {
2011                 _E("failed to get sigchld fd");
2012                 return -1;
2013         }
2014
2015         pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_sigchild, 0, 0);
2016         if (pollfd == 0) {
2017                 close(fd);
2018                 return -1;
2019         }
2020
2021         return 0;
2022 }
2023
2024 static int __init_label_monitor_fd(void)
2025 {
2026         int r;
2027         int fd = -1;
2028         guint pollfd;
2029
2030         r = security_manager_app_labels_monitor_init(&label_monitor);
2031         if (r != SECURITY_MANAGER_SUCCESS)
2032                 return -1;
2033
2034         r = security_manager_app_labels_monitor_process(label_monitor);
2035         if (r != SECURITY_MANAGER_SUCCESS)
2036                 goto err;
2037
2038         security_manager_app_labels_monitor_get_fd(label_monitor, &fd);
2039         if (fd < 0) {
2040                 _E("failed to get fd");
2041                 goto err;
2042         }
2043
2044         pollfd = __poll_fd(fd, G_IO_IN,
2045                         (GSourceFunc)__handle_label_monitor, 0, 0);
2046         if (pollfd == 0)
2047                 goto err;
2048
2049         return 0;
2050
2051 err:
2052         if (fd > 0)
2053                 close(fd);
2054
2055         if (label_monitor) {
2056                 security_manager_app_labels_monitor_finish(label_monitor);
2057                 label_monitor = NULL;
2058         }
2059
2060         return -1;
2061 }
2062
2063 static int __verify_loader_caps(const char *loader)
2064 {
2065         cap_t cap_d;
2066         cap_flag_value_t eff_state;
2067         cap_flag_value_t inh_state;
2068         cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN};
2069         int r;
2070         int i;
2071         int size = ARRAY_SIZE(values);
2072
2073         /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */
2074         if (label_monitor)
2075                 size--;
2076
2077         cap_d = cap_get_file(loader);
2078         if (!cap_d) {
2079                 _E("Failed to get cap from file(%s)", loader);
2080                 return -1;
2081         }
2082
2083         for (i = 0; i < size; i++) {
2084                 r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state);
2085                 if (r != 0) {
2086                         _E("Failed to get cap inh - errno(%d)", errno);
2087                         cap_free(cap_d);
2088                         return -1;
2089                 }
2090
2091                 r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state);
2092                 if (r != 0) {
2093                         _E("Failed to get cap eff - errno(%d)", errno);
2094                         cap_free(cap_d);
2095                         return -1;
2096                 }
2097
2098                 if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
2099                         _E("The %s doesn't have %d cap", loader, values[i]);
2100                         cap_free(cap_d);
2101                         return -1;
2102                 }
2103         }
2104         cap_free(cap_d);
2105
2106         return 0;
2107 }
2108
2109 static void __add_slot_from_info(gpointer data, gpointer user_data)
2110 {
2111         loader_info_t *info = (loader_info_t *)data;
2112         candidate_process_context_t *cpc;
2113         bundle_raw *extra = NULL;
2114         int len;
2115
2116         if (!strcmp(info->exe, "null")) {
2117                 cpc = __add_slot(LAUNCHPAD_TYPE_USER + user_slot_offset,
2118                                 PAD_LOADER_ID_DIRECT,
2119                                 0, info->exe, NULL,
2120                                 0, 0, 0, 0, 0,
2121                                 info->cpu_threshold_max,
2122                                 info->cpu_threshold_min,
2123                                 false,
2124                                 info->app_exists);
2125                 if (cpc == NULL)
2126                         return;
2127
2128                 info->type = LAUNCHPAD_TYPE_USER + user_slot_offset;
2129                 user_slot_offset++;
2130                 return;
2131         }
2132
2133         if (access(info->exe, F_OK | X_OK) == 0) {
2134                 if (__verify_loader_caps(info->exe) < 0)
2135                         return;
2136
2137                 if (info->extra)
2138                         bundle_encode(info->extra, &extra, &len);
2139
2140                 cpc = __add_slot(LAUNCHPAD_TYPE_USER + user_slot_offset,
2141                                 PAD_LOADER_ID_STATIC,
2142                                 0, info->exe, (char *)extra,
2143                                 info->detection_method,
2144                                 info->activation_method,
2145                                 info->deactivation_method,
2146                                 info->ttl,
2147                                 info->timeout_val,
2148                                 info->cpu_threshold_max,
2149                                 info->cpu_threshold_min,
2150                                 info->on_boot,
2151                                 info->app_exists);
2152                 if (cpc == NULL)
2153                         return;
2154
2155                 info->type = LAUNCHPAD_TYPE_USER + user_slot_offset;
2156                 user_slot_offset++;
2157         }
2158 }
2159
2160 static int __add_default_slots(void)
2161 {
2162         if (loader_info_list)
2163                 _loader_info_dispose(loader_info_list);
2164
2165         loader_info_list = _loader_info_load(LOADER_INFO_PATH);
2166         if (loader_info_list == NULL)
2167                 return -1;
2168
2169         user_slot_offset = 0;
2170         g_list_foreach(loader_info_list, __add_slot_from_info, NULL);
2171         __add_idle_checker(0, candidate_slot_list);
2172
2173         return 0;
2174 }
2175
2176 static bool __is_low_memory(void)
2177 {
2178         if (__memory_status >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
2179                 return true;
2180         return false;
2181 }
2182
2183 static void __hw_acceleration_changed_cb(keynode_t *key, void *data)
2184 {
2185         __sys_hwacc = vconf_keynode_get_int(key);
2186         _D("sys hwacc: %d", __sys_hwacc);
2187 }
2188
2189 static void __update_lang(keynode_t *node, void *user_data)
2190 {
2191         char *lang = vconf_keynode_get_str(node);
2192
2193         if (lang)
2194                 setenv("LANG", lang, 1);
2195 }
2196
2197 static void __memory_status_changed_cb(keynode_t *node, void *data)
2198 {
2199         candidate_process_context_t *cpc;
2200         GList *iter = candidate_slot_list;
2201
2202         __memory_status = vconf_keynode_get_int(node);
2203         if (__memory_status >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) {
2204                 _W("Low memory");
2205                 while (iter) {
2206                         cpc = (candidate_process_context_t *)iter->data;
2207                         __update_slot_state(cpc, METHOD_OUT_OF_MEMORY);
2208                         iter = g_list_next(iter);
2209                 }
2210         } else {
2211                 _W("Normal");
2212                 while (iter) {
2213                         cpc = (candidate_process_context_t *)iter->data;
2214                         __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY);
2215                         iter = g_list_next(iter);
2216                 }
2217         }
2218 }
2219
2220 static void __unregister_vconf_events(void)
2221 {
2222         vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY,
2223                         __memory_status_changed_cb);
2224         vconf_ignore_key_changed(VCONFKEY_LANGSET,
2225                         __update_lang);
2226         vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2227                         __hw_acceleration_changed_cb);
2228 }
2229
2230 static int __register_vconf_events(void)
2231 {
2232         int r;
2233         char *lang;
2234
2235         r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
2236         if (r != VCONF_OK)
2237                 _E("Failed to get vconf hw acceleration. err = %d", r);
2238
2239         r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
2240                         __hw_acceleration_changed_cb, NULL);
2241         if (r != VCONF_OK) {
2242                 _E("Failed to register callback for hw acceleration. err = %d",
2243                                 r);
2244         }
2245
2246         lang = vconf_get_str(VCONFKEY_LANGSET);
2247         if (lang) {
2248                 setenv("LANG", lang, 1);
2249                 free(lang);
2250         }
2251
2252         r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
2253         if (r != VCONF_OK)
2254                 _E("Failed to register callback for langset. err = %d", r);
2255
2256         r = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &__memory_status);
2257         if (r != VCONF_OK)
2258                 _E("Failed to get vconf low memory. err = %d", r);
2259
2260         r = vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY,
2261                         __memory_status_changed_cb, NULL);
2262         if (r != 0)
2263                 _E("Failed to register callback for low memory. err = %d", r);
2264
2265         return 0;
2266 }
2267
2268 static gboolean __handle_logger(gpointer data)
2269 {
2270         loader_context_t *lc = (loader_context_t *)data;
2271         int fd = lc->gpollfd->fd;
2272         app_pkt_t *pkt = NULL;
2273         struct ucred cr;
2274         int clifd = -1;
2275
2276         pkt = _accept_recv_pkt_raw(fd, &clifd, &cr);
2277         if (!pkt) {
2278                 _E("Failed to receive the packet");
2279                 return G_SOURCE_CONTINUE;
2280         }
2281
2282         if (getuid() != cr.uid) {
2283                 _E("Invalid caller");
2284                 goto end;
2285         }
2286
2287         if (pkt->len <= 0) {
2288                 _E("Invalid message");
2289                 goto end;
2290         }
2291
2292         SECURE_LOGE("[%d] %s", cr.pid, (const char *)pkt->data);
2293
2294 end:
2295         if (clifd != -1)
2296                 close(clifd);
2297         if (pkt)
2298                 free(pkt);
2299
2300         return G_SOURCE_CONTINUE;
2301 }
2302
2303 static int __init_logger_fd(void)
2304 {
2305         int fd;
2306         guint pollfd;
2307
2308         fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK);
2309         if (fd < 0) {
2310                 _E("Failed to create logger socker");
2311                 return -1;
2312         }
2313
2314         pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_logger, 0, 0);
2315         if (pollfd == 0) {
2316                 close(fd);
2317                 return -1;
2318         }
2319
2320         return 0;
2321 }
2322
2323 static int __before_loop(int argc, char **argv)
2324 {
2325         int ret;
2326
2327         ret = __sequencer_init();
2328         if (ret < 0) {
2329                 _E("Failed to initialize sequencer");
2330                 return -1;
2331         }
2332
2333         ret = __init_sigchild_fd();
2334         if (ret != 0) {
2335                 _E("__init_sigchild_fd() failed");
2336                 return -1;
2337         }
2338
2339         ret = __init_launchpad_fd(argc, argv);
2340         if (ret != 0) {
2341                 _E("__init_launchpad_fd() failed");
2342                 return -1;
2343         }
2344
2345         ret = __init_logger_fd();
2346         if (ret != 0) {
2347                 _E("__init_logger_fd() failed");
2348                 return -1;
2349         }
2350
2351         ret = __init_label_monitor_fd();
2352         if (ret != 0)
2353                 _W("Failed to initialize label monitor");
2354
2355         __add_default_slots();
2356         launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH);
2357
2358         ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
2359         if (ret < 0)
2360                 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL);
2361
2362         __pid_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2363                         NULL, free);
2364         if (!__pid_table) {
2365                 _E("Failed to create pid table");
2366                 return -1;
2367         }
2368
2369         __register_vconf_events();
2370
2371         return 0;
2372 }
2373
2374 static void __after_loop(void)
2375 {
2376         __unregister_vconf_events();
2377         if (__pid_table)
2378                 g_hash_table_destroy(__pid_table);
2379
2380         if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
2381                 _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
2382
2383         _debug_fini();
2384         _launcher_info_unload(launcher_info_list);
2385
2386         if (label_monitor)
2387                 security_manager_app_labels_monitor_finish(label_monitor);
2388
2389         __sequencer_fini();
2390 }
2391
2392 int main(int argc, char **argv)
2393 {
2394         GMainLoop *mainloop = NULL;
2395
2396         mainloop = g_main_loop_new(NULL, FALSE);
2397         if (!mainloop) {
2398                 _E("Failed to create glib main loop");
2399                 return -1;
2400         }
2401
2402         if (__before_loop(argc, argv) != 0) {
2403                 _E("process-pool Initialization failed!");
2404                 return -1;
2405         }
2406
2407 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
2408         _set_priority(-12);
2409 #endif
2410         g_main_loop_run(mainloop);
2411
2412         __after_loop();
2413
2414         return -1;
2415 }
2416