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