91b19b1cce50facb409f00919e4ddb933cffd11d
[platform/core/appfw/pkgmgr-server.git] / src / pkgmgr-server.c
1 /*
2  * slp-pkgmgr
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7  * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <sys/stat.h>
32 #include <dirent.h>
33 #include <sys/types.h>
34 #include <fcntl.h>
35 #include <signal.h>
36 #include <grp.h>
37
38 #include <glib.h>
39 #include <gio/gio.h>
40
41 #include <pkgmgr-info.h>
42 #include <pkgmgr/pkgmgr_parser_db.h>
43 #include <tzplatform_config.h>
44 #include <drm-tizen-apps.h>
45
46 #include "pkgmgr_installer.h"
47 #include "pkgmgr-server.h"
48 #include "pm-queue.h"
49 #include "package-manager.h"
50
51 #define BUFMAX 128
52 #define NO_MATCHING_FILE 11
53
54 #define OWNER_ROOT 0
55 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
56
57 #define EXT_STORAGE_GROUP 10001
58 #define EXT_STORAGE_APPDATA_GROUP 10002
59 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
60
61 typedef struct  {
62         char **env;
63         uid_t uid;
64         gid_t gid;
65 } user_ctx;
66
67
68 /*
69 8 bit value to represent maximum 8 backends.
70 Each bit position corresponds to a queue slot which
71 is dynamically determined.
72 */
73 char backend_busy = 0;
74 extern int num_of_backends;
75
76 struct signal_info_t {
77         pid_t pid;
78         int status;
79 };
80
81 static int pipe_sig[2];
82 static GIOChannel *pipe_io;
83 static guint pipe_wid;
84
85 backend_info *begin;
86 extern queue_info_map *start;
87 extern int entries;
88
89 GMainLoop *mainloop = NULL;
90
91
92 /* operation_type */
93 typedef enum {
94         OPERATION_INSTALL = 0,
95         OPERATION_UNINSTALL,
96         OPERATION_ACTIVATE,
97         OPERATION_REINSTALL,
98         OPERATION_MAX
99 } OPERATION_TYPE;
100
101 static int __check_backend_status_for_exit(void);
102 static int __check_queue_status_for_exit(void);
103 static int __is_backend_busy(int position);
104 static void __set_backend_busy(int position);
105 static void __set_backend_free(int position);
106 static void sighandler(int signo);
107
108 gboolean exit_server(void *data);
109
110 /* To check whether a particular backend is free/busy*/
111 static int __is_backend_busy(int position)
112 {
113         return backend_busy & 1<<position;
114 }
115 /*To set a particular backend as busy*/
116 static void __set_backend_busy(int position)
117 {
118         backend_busy = backend_busy | 1<<position;
119 }
120 /*To set a particular backend as free */
121 static void __set_backend_free(int position)
122 {
123         backend_busy = backend_busy & ~(1<<position);
124 }
125
126 static void __send_app_signal(uid_t uid, const char *req_id,
127                 const char *pkgid, const char *appid,
128                 const char *key, const char *val, int req_type)
129 {
130         pkgmgr_installer *pi;
131
132         pi = pkgmgr_installer_new();
133         if (!pi) {
134                 DBG("Failure in creating the pkgmgr_installer object");
135                 return;
136         }
137
138         if (pkgmgr_installer_set_uid(pi, uid))
139                 goto catch;
140
141         switch (req_type) {
142         case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
143         case PKGMGR_REQUEST_TYPE_ENABLE_APP:
144                 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_ENABLE_APP))
145                         goto catch;
146                 break;
147         case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
148         case PKGMGR_REQUEST_TYPE_DISABLE_APP:
149                 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_DISABLE_APP))
150                         goto catch;
151                 break;
152         case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
153                 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN))
154                         goto catch;
155                 break;
156         case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
157                 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN))
158                         goto catch;
159                 break;
160         default:
161                 DBG("Unsupported req_type[%d]", req_type);
162                 goto catch;
163         }
164
165         if (pkgmgr_installer_set_session_id(pi, req_id))
166                 goto catch;
167         pkgmgr_installer_send_app_signal(pi, "app", pkgid, appid, key, val);
168
169 catch:
170         pkgmgr_installer_free(pi);
171
172         return;
173 }
174
175 static void send_fail_signal(char *pname, char *ptype, char *args)
176 {
177         DBG("send_fail_signal start\n");
178         gboolean ret_parse;
179         gint argcp;
180         gchar **argvp;
181         GError *gerr = NULL;
182         pkgmgr_installer *pi;
183         pi = pkgmgr_installer_new();
184         if (!pi) {
185                 DBG("Failure in creating the pkgmgr_installer object");
186                 return;
187         }
188         ret_parse = g_shell_parse_argv(args,
189                                        &argcp, &argvp, &gerr);
190         if (FALSE == ret_parse) {
191                 DBG("Failed to split args: %s", args);
192                 DBG("messsage: %s", gerr->message);
193                 pkgmgr_installer_free(pi);
194                 return;
195         }
196
197         pkgmgr_installer_receive_request(pi, argcp, argvp);
198         pkgmgr_installer_send_signal(pi, ptype, pname, "end", "fail");
199         pkgmgr_installer_free(pi);
200         return;
201 }
202
203 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data)
204 {
205         int x;
206         GError *err = NULL;
207         GIOStatus s;
208         gsize len;
209         struct signal_info_t info;
210         backend_info *ptr = begin;
211
212         s = g_io_channel_read_chars(io, (gchar *)&info, sizeof(struct signal_info_t), &len, &err);
213         if (s != G_IO_STATUS_NORMAL) {
214                 ERR("Signal pipe read failed: %s", err->message);
215                 g_error_free(err);
216                 return TRUE;
217         }
218
219         for (x = 0; x < num_of_backends; x++, ptr++) {
220                 if (ptr && ptr->pid == info.pid)
221                         break;
222         }
223
224         if (x == num_of_backends) {
225                 ERR("Unknown child exit");
226                 return -1;
227         }
228
229         __set_backend_free(x);
230         if (WIFSIGNALED(info.status) || WEXITSTATUS(info.status)) {
231                 send_fail_signal(ptr->pkgid, ptr->pkgtype, ptr->args);
232                 DBG("backend[%s] exit with error", ptr->pkgtype);
233         } else {
234                 DBG("backend[%s] exit", ptr->pkgtype);
235         }
236
237         g_idle_add(queue_job, NULL);
238
239         return TRUE;
240 }
241
242 static int __init_backend_info(void)
243 {
244         backend_info *ptr;
245
246         /*Allocate memory for holding pid, pkgtype and pkgid*/
247         ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
248         if (ptr == NULL) {
249                 DBG("Malloc Failed\n");
250                 return -1;
251         }
252         begin = ptr;
253
254         if (pipe(pipe_sig)) {
255                 ERR("create pipe failed");
256                 return -1;
257         }
258
259         pipe_io = g_io_channel_unix_new(pipe_sig[0]);
260         g_io_channel_set_encoding(pipe_io, NULL, NULL);
261         g_io_channel_set_buffered(pipe_io, FALSE);
262         pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
263
264         return 0;
265 }
266
267 static void __fini_backend_info(void)
268 {
269         g_source_remove(pipe_wid);
270         g_io_channel_unref(pipe_io);
271         close(pipe_sig[0]);
272         close(pipe_sig[1]);
273
274         /*Free backend info */
275         free(begin);
276 }
277
278 static void sighandler(int signo)
279 {
280         struct signal_info_t info;
281         char buf[1024] = {0, };
282
283         info.pid = waitpid(-1, &info.status, WNOHANG);
284         if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
285                 ERR("failed to write result: %s", strerror_r(errno, buf, sizeof(buf)));
286 }
287
288 static int __register_signal_handler(void)
289 {
290         static int sig_reg = 0;
291         struct sigaction act;
292
293         if (sig_reg)
294                 return 0;
295
296         act.sa_handler = sighandler;
297         sigemptyset(&act.sa_mask);
298         act.sa_flags = SA_NOCLDSTOP;
299         if (sigaction(SIGCHLD, &act, NULL) < 0) {
300                 ERR("signal: SIGCHLD failed\n");
301                 return -1;
302         }
303
304         g_timeout_add_seconds(2, exit_server, NULL);
305
306         sig_reg = 1;
307         return 0;
308 }
309
310 static int __check_backend_status_for_exit(void)
311 {
312         int i = 0;
313         for(i = 0; i < num_of_backends; i++)
314         {
315                 if (!__is_backend_busy(i))
316                         continue;
317                 else
318                         return 0;
319         }
320         return 1;
321 }
322
323 static int __check_queue_status_for_exit(void)
324 {
325         pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
326         queue_info_map *ptr = NULL;
327         ptr = start;
328         int i = 0;
329         int c = 0;
330         int slot = -1;
331         for(i = 0; i < entries; i++)
332         {
333                 if (ptr->queue_slot <= slot) {
334                         ptr++;
335                         continue;
336                 }
337                 else {
338                         head[c] = ptr->head;
339                         slot = ptr->queue_slot;
340                         c++;
341                         ptr++;
342                 }
343         }
344         for(i = 0; i < num_of_backends; i++)
345         {
346                 if (!head[i])
347                         continue;
348                 else
349                         return 0;
350         }
351         return 1;
352 }
353
354 gboolean exit_server(void *data)
355 {
356         DBG("exit_server Start\n");
357         if (__check_backend_status_for_exit() &&
358                         __check_queue_status_for_exit()) {
359                 if (!getenv("PMS_STANDALONE")) {
360                         g_main_loop_quit(mainloop);
361                         return FALSE;
362                 }
363         }
364         return TRUE;
365 }
366
367 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
368 {
369         int fd;
370         int ret;
371         if (buf == NULL || path == NULL)
372                 return -1;
373         fd = open(path, O_RDONLY);
374         if (fd < 0)
375                 return -1;
376         ret = read(fd, buf, size - 1);
377         if (ret <= 0) {
378                 close(fd);
379                 return -1;
380         } else
381                 buf[ret] = 0;
382         close(fd);
383         return ret;
384 }
385
386 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
387                         const char *cmdline, const char *apppath)
388 {
389         int pid = 0;
390
391         if (strcmp(cmdline, apppath) == 0) {
392                 pid = atoi(dname);
393                 if (pid != getpgid(pid))
394                         pid = 0;
395         }
396         return pid;
397 }
398
399 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
400 {
401         DIR *dp;
402         struct dirent dentry, *result;
403         int pid;
404         int ret;
405         char buf[1024] = {'\0'};
406         int pgid;
407
408         dp = opendir("/proc");
409         if (dp == NULL) {
410                 return -1;
411         }
412
413         for (ret = readdir_r(dp, &dentry, &result);
414                         ret == 0 && result != NULL;
415                         ret = readdir_r(dp, &dentry, &result)) {
416                 if (!isdigit(dentry.d_name[0]))
417                         continue;
418
419                 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry.d_name);
420                 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
421                 if (ret <= 0)
422                         continue;
423
424                 pid = __pkgcmd_find_pid_by_cmdline(dentry.d_name, buf, apppath);
425                 if (pid > 0) {
426                         if (option == 0) {
427                                 closedir(dp);
428                                 return pid;
429                         }
430                         pgid = getpgid(pid);
431                         if (pgid <= 1) {
432                                 closedir(dp);
433                                 return -1;
434                         }
435                         if (killpg(pgid, SIGKILL) < 0) {
436                                 closedir(dp);
437                                 return -1;
438                         }
439                         closedir(dp);
440                         return pid;
441                 }
442         }
443         closedir(dp);
444         return 0;
445 }
446
447 static void __make_pid_info_file(char *req_key, int pid)
448 {
449         FILE* file;
450         int fd;
451         char buf[MAX_PKG_TYPE_LEN] = {0};
452         char info_file[PATH_MAX] = {'\0'};
453
454         if(req_key == NULL)
455                 return;
456
457         snprintf(info_file, PATH_MAX, "/tmp/pkgmgr/%s", req_key);
458
459         DBG("info_path(%s)", info_file);
460         file = fopen(info_file, "w");
461         if (file == NULL) {
462                 ERR("Couldn't open the file(%s)", info_file);
463                 return;
464         }
465
466         snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
467         fwrite(buf, 1, strlen(buf), file);
468
469         fflush(file);
470         fd = fileno(file);
471         fsync(fd);
472         fclose(file);
473 }
474
475 static int __kill_app(char *appid, uid_t uid)
476 {
477         pkgmgrinfo_appinfo_h appinfo;
478         int ret = PMINFO_R_ERROR;
479         char *exec = NULL;
480
481         ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &appinfo);
482         if (ret != PMINFO_R_OK)
483                 return PMINFO_R_ERROR;
484
485         ret = pkgmgrinfo_appinfo_get_exec(appinfo, &exec);
486         if (ret != PMINFO_R_OK) {
487                 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
488                 return PMINFO_R_ERROR;
489         }
490
491         ret = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
492         if (ret != PMINFO_R_OK) {
493                 DBG("failed to kill app[%s], exec[%s]", appid, exec);
494         }
495
496         pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
497         return ret;
498 }
499
500 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
501 {
502         char *pkgid;
503         char *exec;
504         int ret;
505         int pid = -1;
506
507         if (handle == NULL) {
508                 perror("appinfo handle is NULL\n");
509                 exit(1);
510         }
511         ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
512         if (ret) {
513                 perror("Failed to get app exec path\n");
514                 exit(1);
515         }
516         ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
517         if (ret) {
518                 perror("Failed to get pkgid\n");
519                 exit(1);
520         }
521
522         if (strcmp(user_data, "kill") == 0)
523                 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
524         else if(strcmp(user_data, "check") == 0)
525                 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
526
527         __make_pid_info_file(pkgid, pid);
528
529         return 0;
530 }
531
532 void free_user_context(user_ctx* ctx)
533 {
534         char **env = NULL;
535         int i = 0;
536         if (!ctx)
537                 return;
538         env = ctx->env;
539         //env variable ends by NULL element
540         while (env[i]) {
541                 free(env[i]);
542                 i++;
543         }
544         free(env);
545         env = NULL;
546         free(ctx);
547 }
548
549 int set_environement(user_ctx *ctx)
550 {
551         int i = 0;
552         int res = 0;
553         char **env = NULL;
554         gid_t groups[] = {EXT_STORAGE_GROUP, EXT_STORAGE_APPDATA_GROUP};
555
556         if (!ctx)
557                 return -1;;
558         if (setgid(ctx->gid)) {
559                 ERR("setgid failed: %d", errno);
560                 return -1;
561         }
562         if (setgroups(ARRAY_SIZE(groups), groups) < 0) {
563                 ERR("setgroups failed: %d", errno);
564                 return -1;
565         }
566         if (setuid(ctx->uid)) {
567                 ERR("setuid failed: %d", errno);
568                 return -1;
569         }
570         env = ctx->env;
571         //env variable ends by NULL element
572         while (env[i]) {
573                 if (putenv(env[i]) != 0)
574                         res = -1;
575                 i++;
576         }
577         return res;
578 }
579
580 user_ctx *get_user_context(uid_t uid)
581 {
582         /* we can use getpwnam because this is used only after a
583          * fork and just before an execv
584          * No concurrencial call can corrupt the data
585          * returned by getpwuid
586          */
587         user_ctx *context_res;
588         char **env = NULL;
589         char buf[1024] = {0, };
590         struct passwd pwd, *result;
591         int len;
592         int ret = 0;
593         int i;
594
595         ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
596         if (ret != 0 || result == NULL)
597                 return NULL;
598
599         do {
600                 context_res = (user_ctx *)malloc(sizeof(user_ctx));
601                 if (!context_res) {
602                         ret = -1;
603                         break;
604                 }
605                 env = (char **)malloc(3 * sizeof(char *));
606                 if (!env) {
607                         ret = -1;
608                         break;
609                 }
610                 // Build environment context
611                 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
612                 env[0] = (char *)malloc((len + 1) * sizeof(char));
613                 if(env[0] == NULL) {
614                         ret = -1;
615                         break;
616                 }
617                 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
618                 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
619                 env[1] = (char *)malloc((len + 1) * sizeof(char));
620                 if(env[1] == NULL) {
621                         ret = -1;
622                         break;
623                 }
624                 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
625                 env[2] = NULL;
626         } while (0);
627
628         if (ret == -1) {
629                 free(context_res);
630                 context_res = NULL;
631                 i = 0;
632                 //env variable ends by NULL element
633                 while (env && env[i]) {
634                         free(env[i]);
635                         i++;
636                 }
637                 free(env);
638                 env = NULL;
639         } else {
640                 context_res->env = env;
641                 context_res->uid = uid;
642                 context_res->gid = pwd.pw_gid;
643         }
644         return context_res;
645 }
646
647 static char **__generate_argv(const char *args)
648 {
649         /* Create args vector
650          * req_id + pkgid + args
651          *
652          * vector size = # of args +
653          *(req_id + pkgid + NULL termination = 3)
654          * Last value must be NULL for execv.
655          */
656         gboolean ret_parse;
657         gint argcp;
658         gchar **argvp;
659         GError *gerr = NULL;
660         int i;
661
662         ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
663         if (FALSE == ret_parse) {
664                 DBG("Failed to split args: %s", args);
665                 DBG("messsage: %s", gerr->message);
666                 exit(1);
667         }
668
669         /* dbg */
670         for (i = 0; i < argcp; i++)
671                 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
672
673         return argvp;
674 }
675
676 void __set_environment(gpointer user_data)
677 {
678         user_ctx *ctx = (user_ctx *)user_data;
679
680         if (set_environement(ctx))
681                 DBG("Failed to set env for the user : %d", ctx->uid);
682 }
683
684 static int __fork_and_exec_with_args(char **argv, uid_t uid)
685 {
686         user_ctx* user_context;
687         GError *error = NULL;
688         gboolean ret;
689         int pid;
690
691         user_context = get_user_context(uid);
692         if (!user_context) {
693                 DBG("Failed to getenv for the user : %d", uid);
694                 return -1;
695         }
696
697         ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
698                         __set_environment, (gpointer)user_context, &pid,
699                         &error);
700         if (ret != TRUE) {
701                 ERR("Failed to excute backend: %s", error->message);
702                 g_error_free(error);
703         }
704
705         free_user_context(user_context);
706
707         return pid;
708 }
709
710 static int __change_item_info(pm_dbus_msg *item, uid_t uid, bool *is_global)
711 {
712         int ret = 0;
713         char *pkgid = NULL;
714         pkgmgrinfo_appinfo_h handle = NULL;
715
716         switch (item->req_type) {
717         case PKGMGR_REQUEST_TYPE_DISABLE_APP:
718         case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
719         case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
720         case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
721                 ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle);
722                 break;
723         case PKGMGR_REQUEST_TYPE_ENABLE_APP:
724         case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
725                 ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle);
726                 break;
727         default:
728                 return PMINFO_R_ERROR;
729         }
730
731         if (ret != PMINFO_R_OK)
732                 return PMINFO_R_ERROR;
733
734         ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
735         if (ret != PMINFO_R_OK)
736                 goto catch;
737
738         if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_APP
739                         || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_APP)
740                         && *is_global) {
741                         ret = PMINFO_R_ERROR;
742                         goto catch;
743         } else if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID
744                         || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
745                         && !*is_global) {
746                         ret = PMINFO_R_ERROR;
747                         goto catch;
748         }
749
750         ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
751         if (ret != PMINFO_R_OK)
752                 goto catch;
753
754         strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1);
755         memset((item->pkgid), 0, MAX_PKG_NAME_LEN);
756         strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
757
758 catch:
759         pkgmgrinfo_appinfo_destroy_appinfo(handle);
760
761         return ret;
762 }
763
764 static int __process_install(pm_dbus_msg *item)
765 {
766         char *backend_cmd;
767         char **argv;
768         char args[MAX_PKG_ARGS_LEN] = {'\0', };
769         int pid;
770
771         backend_cmd = _get_backend_cmd(item->pkg_type);
772         if (backend_cmd == NULL)
773                 return -1;
774
775         snprintf(args, sizeof(args), "%s -k %s -i %s %s", backend_cmd,
776                         item->req_id, item->pkgid, item->args);
777
778         argv = __generate_argv(args);
779
780         pid = __fork_and_exec_with_args(argv, item->uid);
781         g_strfreev(argv);
782         free(backend_cmd);
783
784         return pid;
785 }
786
787 static int __process_mount_install(pm_dbus_msg *item)
788 {
789         char *backend_cmd;
790         char **argv;
791         char args[MAX_PKG_ARGS_LEN] = {'\0', };
792         int pid;
793
794         backend_cmd = _get_backend_cmd(item->pkg_type);
795         if (backend_cmd == NULL)
796                 return -1;
797
798         snprintf(args, sizeof(args), "%s -k %s -w %s %s", backend_cmd,
799                                          item->req_id, item->pkgid, item->args);
800
801         argv = __generate_argv(args);
802
803         pid = __fork_and_exec_with_args(argv, item->uid);
804         g_strfreev(argv);
805         free(backend_cmd);
806
807         return pid;
808 }
809
810 static int __process_reinstall(pm_dbus_msg *item)
811 {
812         char *backend_cmd;
813         char **argv;
814         char args[MAX_PKG_ARGS_LEN];
815         int pid;
816
817         backend_cmd = _get_backend_cmd(item->pkg_type);
818         if (backend_cmd == NULL)
819                 return -1;
820
821         snprintf(args, sizeof(args), "%s -k %s -r %s", backend_cmd,
822                         item->req_id, item->pkgid);
823         argv = __generate_argv(args);
824
825         pid = __fork_and_exec_with_args(argv, item->uid);
826
827         g_strfreev(argv);
828         free(backend_cmd);
829
830         return pid;
831 }
832
833 static int __process_uninstall(pm_dbus_msg *item)
834 {
835         char *backend_cmd;
836         char **argv;
837         char args[MAX_PKG_ARGS_LEN];
838         int pid;
839
840         backend_cmd = _get_backend_cmd(item->pkg_type);
841         if (backend_cmd == NULL)
842                 return -1;
843
844         snprintf(args, sizeof(args), "%s -k %s -d %s", backend_cmd,
845                         item->req_id, item->pkgid);
846         argv = __generate_argv(args);
847
848         pid = __fork_and_exec_with_args(argv, item->uid);
849
850         g_strfreev(argv);
851         free(backend_cmd);
852
853         return pid;
854 }
855
856 static int __process_move(pm_dbus_msg *item)
857 {
858         char *backend_cmd;
859         char **argv;
860         char args[MAX_PKG_ARGS_LEN];
861         int pid;
862
863         backend_cmd = _get_backend_cmd(item->pkg_type);
864         if (backend_cmd == NULL)
865                 return -1;
866
867         snprintf(args, sizeof(args), "%s -k %s -m %s -t %s", backend_cmd,
868                         item->req_id, item->pkgid, item->args);
869         argv = __generate_argv(args);
870
871         pid = __fork_and_exec_with_args(argv, item->uid);
872
873         g_strfreev(argv);
874         free(backend_cmd);
875
876         return pid;
877 }
878
879 static int __process_enable_pkg(pm_dbus_msg *item)
880 {
881         /* TODO */
882         return 0;
883 }
884
885 static int __process_disable_pkg(pm_dbus_msg *item)
886 {
887         /* TODO */
888         return 0;
889 }
890
891 static int __process_enable_app(pm_dbus_msg *item)
892 {
893         int ret = -1;
894         bool is_global = false;
895
896         __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
897                         PKGMGR_INSTALLER_START_KEY_STR,
898                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, item->req_type);
899
900         /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
901         ret = __change_item_info(item, item->uid, &is_global);
902         if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
903                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
904                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
905                                 item->req_type);
906                 return ret;
907         }
908
909         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 0);
910         if (ret != PMINFO_R_OK)
911                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
912                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
913                                 item->req_type);
914         else
915                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
916                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
917                                 item->req_type);
918
919
920         return ret;
921 }
922
923 static int __process_disable_app(pm_dbus_msg *item)
924 {
925         int ret = -1;
926         bool is_global = false;
927
928         __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
929                         PKGMGR_INSTALLER_START_KEY_STR,
930                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, item->req_type);
931
932         /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
933         ret = __change_item_info(item, item->uid, &is_global);
934         if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
935                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
936                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
937                                 item->req_type);
938                 return ret;
939         }
940
941         ret = __kill_app(item->appid, item->uid);
942         if (ret != PMINFO_R_OK) {
943                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
944                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
945                                 item->req_type);
946         }
947
948         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1);
949         if (ret != PMINFO_R_OK)
950                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
951                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
952                                 item->req_type);
953         else
954                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
955                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
956                                 item->req_type);
957
958         return ret;
959 }
960
961 static int __process_enable_global_app_for_uid(pm_dbus_msg *item)
962 {
963         int ret = -1;
964         bool is_global = true;
965
966         __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
967                         PKGMGR_INSTALLER_START_KEY_STR,
968                         PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID, item->req_type);
969
970         /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
971         ret = __change_item_info(item, item->uid, &is_global);
972         if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
973                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
974                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
975                                 item->req_type);
976                 return ret;
977         }
978
979         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0);
980         if (ret != PMINFO_R_OK)
981                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
982                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
983                                 item->req_type);
984         else
985                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
986                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
987                                 item->req_type);
988
989         return ret;
990 }
991
992 static int __process_disable_global_app_for_uid(pm_dbus_msg *item)
993 {
994         int ret = -1;
995         bool is_global = true;
996
997         __send_app_signal(item->uid, item->req_id,
998                         item->pkgid, item->pkgid,
999                         PKGMGR_INSTALLER_START_KEY_STR,
1000                         PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID, item->req_type);
1001
1002         /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1003         ret = __change_item_info(item, GLOBAL_USER, &is_global);
1004         if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1005                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1006                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1007                                 item->req_type);
1008                 return ret;
1009         }
1010
1011         ret = __kill_app(item->appid, item->uid);
1012         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid,
1013                 item->uid, 1);
1014
1015         if (ret != PMINFO_R_OK)
1016                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1017                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1018                                 item->req_type);
1019         else
1020                 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1021                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1022                                 item->req_type);
1023
1024         return ret;
1025 }
1026
1027 static int __process_getsize(pm_dbus_msg *item)
1028 {
1029         static const char *backend_cmd = "/usr/bin/pkg_getsize";
1030         char **argv;
1031         char args[MAX_PKG_ARGS_LEN];
1032         int pid;
1033
1034         snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid,
1035                         item->args, item->req_id);
1036         argv = __generate_argv(args);
1037         pid = __fork_and_exec_with_args(argv, item->uid);
1038
1039         g_strfreev(argv);
1040
1041         return pid;
1042 }
1043
1044 static int __process_cleardata(pm_dbus_msg *item)
1045 {
1046         char *backend_cmd;
1047         char **argv;
1048         char args[MAX_PKG_ARGS_LEN];
1049         int pid;
1050
1051         backend_cmd = _get_backend_cmd(item->pkg_type);
1052         if (backend_cmd == NULL)
1053                 return -1;
1054
1055         /* TODO: set movetype */
1056         snprintf(args, sizeof(args), "%s -k %s -c %s", backend_cmd,
1057                         item->req_id, item->pkgid);
1058         argv = __generate_argv(args);
1059
1060         pid = __fork_and_exec_with_args(argv, item->uid);
1061
1062         g_strfreev(argv);
1063         free(backend_cmd);
1064
1065         return pid;
1066 }
1067
1068 static int __process_clearcache(pm_dbus_msg *item)
1069 {
1070         static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1071         char **argv;
1072         char args[MAX_PKG_ARGS_LEN];
1073         int pid;
1074
1075         snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid);
1076         argv = __generate_argv(args);
1077         pid = __fork_and_exec_with_args(argv, item->uid);
1078
1079         g_strfreev(argv);
1080
1081         return pid;
1082 }
1083
1084 static int __process_kill(pm_dbus_msg *item)
1085 {
1086         int ret;
1087         pkgmgrinfo_pkginfo_h handle;
1088
1089         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1090                         &handle);
1091         if (ret < 0) {
1092                 ERR("Failed to get handle");
1093                 return -1;
1094         }
1095
1096         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1097                         __pkgcmd_app_cb, "kill", item->uid);
1098         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1099         if (ret < 0) {
1100                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1101                 return -1;
1102         }
1103
1104         return 0;
1105 }
1106
1107 static int __process_check(pm_dbus_msg *item)
1108 {
1109         int ret;
1110         pkgmgrinfo_pkginfo_h handle;
1111
1112         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1113                         &handle);
1114         if (ret < 0) {
1115                 ERR("Failed to get handle");
1116                 return -1;
1117         }
1118
1119         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1120                         __pkgcmd_app_cb, "check", item->uid);
1121         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1122         if (ret < 0) {
1123                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1124                 return -1;
1125         }
1126
1127         return 0;
1128 }
1129
1130 static int __process_generate_license_request(pm_dbus_msg *item)
1131 {
1132         int ret;
1133         char *resp_data;
1134         char req_data[MAX_PKG_ARGS_LEN];
1135         unsigned int req_data_len;
1136         char license_url[MAX_PKG_ARGS_LEN];
1137         unsigned int license_url_len;
1138
1139         resp_data = item->args;
1140         req_data_len = sizeof(req_data);
1141         license_url_len = sizeof(license_url);
1142
1143         ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1144                         req_data, &req_data_len, license_url, &license_url_len);
1145         if (ret != TADC_SUCCESS) {
1146                 ERR("drm_tizen_generate_license_request failed: %d", ret);
1147                 __return_value_to_caller(item->req_id, g_variant_new("(iss)",
1148                                         PKGMGR_R_ESYSTEM, "", ""));
1149                 return -1;
1150         }
1151
1152         __return_value_to_caller(item->req_id,
1153                         g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1154                                 license_url));
1155
1156         return 0;
1157 }
1158
1159 static int __process_register_license(pm_dbus_msg *item)
1160 {
1161         int ret;
1162         char *resp_data;
1163
1164         resp_data = item->args;
1165
1166         ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1167         if (ret != TADC_SUCCESS) {
1168                 ERR("drm_tizen_register_license failed: %d", ret);
1169                 __return_value_to_caller(item->req_id,
1170                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1171                 return -1;
1172         }
1173
1174         __return_value_to_caller(item->req_id,
1175                         g_variant_new("(i)", PKGMGR_R_OK));
1176
1177         return 0;
1178 }
1179
1180 static int __process_decrypt_package(pm_dbus_msg *item)
1181 {
1182         int ret;
1183         char *drm_file_path;
1184         char *decrypted_file_path;
1185
1186         drm_file_path = item->pkgid;
1187         decrypted_file_path = item->args;
1188
1189         /* TODO: check ownership of decrypted file */
1190         ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1191                         decrypted_file_path, strlen(decrypted_file_path));
1192         if (ret != TADC_SUCCESS) {
1193                 ERR("drm_tizen_register_license failed: %d", ret);
1194                 __return_value_to_caller(item->req_id,
1195                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1196                 return -1;
1197         }
1198
1199         __return_value_to_caller(item->req_id,
1200                         g_variant_new("(i)", PKGMGR_R_OK));
1201
1202         return 0;
1203 }
1204
1205 static int __process_update_app_splash_screen(pm_dbus_msg *item, int flag)
1206 {
1207         int ret;
1208         bool is_global = false;
1209         const char *val;
1210
1211         ret = __change_item_info(item, item->uid, &is_global);
1212         if (ret != PMINFO_R_OK || strlen(item->appid) == 0)
1213                 return -1;
1214
1215         val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1216                 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1217         __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1218                         PKGMGR_INSTALLER_START_KEY_STR, val, item->req_type);
1219
1220         if (is_global)
1221                 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(
1222                                 item->appid, item->uid, flag);
1223         else
1224                 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1225                         item->appid, item->uid, flag);
1226         if (ret != PMINFO_R_OK)
1227                 __send_app_signal(item->uid, item->req_id, item->pkgid,
1228                                 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1229                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1230                                 item->req_type);
1231         else
1232                 __send_app_signal(item->uid, item->req_id, item->pkgid,
1233                                 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1234                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1235                                 item->req_type);
1236
1237         return ret;
1238 }
1239
1240 static int __process_set_restriction_mode(pm_dbus_msg *item)
1241 {
1242         int ret;
1243         int mode;
1244
1245         mode = atoi(item->args);
1246         ret = _restriction_mode_set(item->uid, item->pkgid, mode);
1247
1248         __return_value_to_caller(item->req_id,
1249                         g_variant_new("(i)", ret));
1250
1251         return ret;
1252 }
1253
1254 static int __process_unset_restriction_mode(pm_dbus_msg *item)
1255 {
1256         int ret;
1257         int mode;
1258
1259         mode = atoi(item->args);
1260         ret = _restriction_mode_unset(item->uid, item->pkgid, mode);
1261
1262         __return_value_to_caller(item->req_id,
1263                         g_variant_new("(i)", ret));
1264
1265         return ret;
1266 }
1267
1268 static int __process_get_restriction_mode(pm_dbus_msg *item)
1269 {
1270         int ret;
1271         int mode = -1;
1272
1273         ret = _restriction_mode_get(item->uid, item->pkgid, &mode);
1274
1275         __return_value_to_caller(item->req_id,
1276                         g_variant_new("(ii)", mode, ret));
1277
1278         return ret;
1279 }
1280
1281 gboolean queue_job(void *data)
1282 {
1283         pm_dbus_msg *item = NULL;
1284         backend_info *ptr;
1285         int x;
1286         int ret;
1287
1288         /* Pop a job from queue */
1289         for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1290                 if (__is_backend_busy(x))
1291                         continue;
1292
1293                 item = _pm_queue_pop(x);
1294                 if (item && item->req_type != -1)
1295                         break;
1296                 free(item);
1297         }
1298
1299         /* all backend messages queue are empty or busy */
1300         if (x == num_of_backends)
1301                 return FALSE;
1302
1303         /*save pkg type and pkg name for future*/
1304         strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
1305         strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
1306         strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN-1);
1307         memset((item->appid),0,MAX_PKG_NAME_LEN);
1308         ptr->uid = item->uid;
1309         DBG("handle request type [%d]", item->req_type);
1310
1311         switch (item->req_type) {
1312         case PKGMGR_REQUEST_TYPE_INSTALL:
1313                 __set_backend_busy(x);
1314                 ret = __process_install(item);
1315                 break;
1316         case PKGMGR_REQUEST_TYPE_MOUNT_INSTALL:
1317                 __set_backend_busy(x);
1318                 ret = __process_mount_install(item);
1319                 break;
1320         case PKGMGR_REQUEST_TYPE_REINSTALL:
1321                 __set_backend_busy(x);
1322                 ret = __process_reinstall(item);
1323                 break;
1324         case PKGMGR_REQUEST_TYPE_UNINSTALL:
1325                 __set_backend_busy(x);
1326                 ret = __process_uninstall(item);
1327                 break;
1328         case PKGMGR_REQUEST_TYPE_MOVE:
1329                 __set_backend_busy(x);
1330                 ret = __process_move(item);
1331                 break;
1332         case PKGMGR_REQUEST_TYPE_ENABLE_PKG:
1333                 ret = __process_enable_pkg(item);
1334                 break;
1335         case PKGMGR_REQUEST_TYPE_DISABLE_PKG:
1336                 ret = __process_disable_pkg(item);
1337                 break;
1338         case PKGMGR_REQUEST_TYPE_ENABLE_APP:
1339                 ret = __process_enable_app(item);
1340                 break;
1341         case PKGMGR_REQUEST_TYPE_DISABLE_APP:
1342                 ret = __process_disable_app(item);
1343                 break;
1344         case PKGMGR_REQUEST_TYPE_GETSIZE:
1345                 __set_backend_busy(x);
1346                 ret = __process_getsize(item);
1347                 break;
1348         case PKGMGR_REQUEST_TYPE_CLEARDATA:
1349                 __set_backend_busy(x);
1350                 ret = __process_cleardata(item);
1351                 break;
1352         case PKGMGR_REQUEST_TYPE_CLEARCACHE:
1353                 __set_backend_busy(x);
1354                 ret = __process_clearcache(item);
1355                 break;
1356         case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1357                 ret = __process_enable_global_app_for_uid(item);
1358                 break;
1359         case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1360                 ret = __process_disable_global_app_for_uid(item);
1361                 break;
1362         case PKGMGR_REQUEST_TYPE_KILL:
1363                 ret = __process_kill(item);
1364                 break;
1365         case PKGMGR_REQUEST_TYPE_CHECK:
1366                 ret = __process_check(item);
1367                 break;
1368         case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1369                 ret = __process_generate_license_request(item);
1370                 break;
1371         case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE:
1372                 ret = __process_register_license(item);
1373                 break;
1374         case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE:
1375                 ret = __process_decrypt_package(item);
1376                 break;
1377         case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1378                 ret = __process_update_app_splash_screen(item, 1);
1379                 break;
1380         case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1381                 ret = __process_update_app_splash_screen(item, 0);
1382                 break;
1383         case PKGMGR_REQUEST_TYPE_SET_RESTRICTION_MODE:
1384                 ret = __process_set_restriction_mode(item);
1385                 break;
1386         case PKGMGR_REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1387                 ret = __process_unset_restriction_mode(item);
1388                 break;
1389         case PKGMGR_REQUEST_TYPE_GET_RESTRICTION_MODE:
1390                 ret = __process_get_restriction_mode(item);
1391                 break;
1392         default:
1393                 ret = -1;
1394                 break;
1395         }
1396
1397         ptr->pid = ret;
1398         free(item);
1399
1400         return FALSE;
1401 }
1402
1403 #define IS_WHITESPACE(CHAR) \
1404 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1405
1406 void _app_str_trim(char *input)
1407 {
1408         char *trim_str = input;
1409
1410         if (input == NULL)
1411                 return;
1412
1413         while (*input != 0) {
1414                 if (!IS_WHITESPACE(*input)) {
1415                         *trim_str = *input;
1416                         trim_str++;
1417                 }
1418                 input++;
1419         }
1420
1421         *trim_str = 0;
1422         return;
1423 }
1424
1425 char *_get_backend_cmd(char *type)
1426 {
1427         FILE *fp = NULL;
1428         char buffer[1024] = { 0 };
1429         char *command = NULL;
1430         int size = 0;
1431         fp = fopen(PKG_CONF_PATH, "r");
1432         if (fp == NULL) {
1433                 return NULL;
1434         }
1435
1436         char *path = NULL;
1437         while (fgets(buffer, 1024, fp) != NULL) {
1438                 if (buffer[0] == '#')
1439                         continue;
1440
1441                 _app_str_trim(buffer);
1442
1443                 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1444                         DBG("buffer [%s]", buffer);
1445                         path = path + strlen(PKG_BACKEND);
1446                         DBG("path [%s]", path);
1447
1448                         command =
1449                             (char *)malloc(sizeof(char) * strlen(path) +
1450                                            strlen(type) + 1);
1451                         if (command == NULL) {
1452                                 fclose(fp);
1453                                 return NULL;
1454                         }
1455
1456                         size = strlen(path) + strlen(type) + 1;
1457                         snprintf(command, size, "%s%s", path, type);
1458                         command[strlen(path) + strlen(type)] = '\0';
1459                         DBG("command [%s]", command);
1460
1461                         if (fp != NULL)
1462                                 fclose(fp);
1463
1464                         return command;
1465                 }
1466
1467                 memset(buffer, 0x00, 1024);
1468         }
1469
1470         if (fp != NULL)
1471                 fclose(fp);
1472
1473         return NULL;            /* cannot find proper command */
1474 }
1475
1476 int main(int argc, char *argv[])
1477 {
1478         int r;
1479
1480         DBG("server start");
1481
1482         r = _pm_queue_init();
1483         if (r) {
1484                 DBG("Queue Initialization Failed\n");
1485                 return -1;
1486         }
1487
1488         r = __init_backend_info();
1489         if (r) {
1490                 DBG("backend info init failed");
1491                 return -1;
1492         }
1493
1494         r = __init_request_handler();
1495         if (r) {
1496                 ERR("dbus init failed");
1497                 return -1;
1498         }
1499
1500         if (__register_signal_handler()) {
1501                 ERR("failed to register signal handler");
1502                 return -1;
1503         }
1504
1505 #if !GLIB_CHECK_VERSION(2,35,0)
1506         g_type_init();
1507 #endif
1508         mainloop = g_main_loop_new(NULL, FALSE);
1509         if (!mainloop) {
1510                 ERR("g_main_loop_new failed");
1511                 return -1;
1512         }
1513
1514         DBG("Main loop is created.");
1515
1516         g_main_loop_run(mainloop);
1517
1518         DBG("Quit main loop.");
1519         __fini_request_handler();
1520         __fini_backend_info();
1521         _pm_queue_final();
1522
1523         DBG("package manager server terminated.");
1524
1525         return 0;
1526 }