fix to check given app handle is from global db or not
[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
340         info.pid = waitpid(-1, &info.status, WNOHANG);
341         if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
342                 ERR("failed to write result: %s", strerror(errno));
343 }
344
345 static int __register_signal_handler(void)
346 {
347         static int sig_reg = 0;
348         struct sigaction act;
349
350         if (sig_reg)
351                 return 0;
352
353         act.sa_handler = sighandler;
354         sigemptyset(&act.sa_mask);
355         act.sa_flags = SA_NOCLDSTOP;
356         if (sigaction(SIGCHLD, &act, NULL) < 0) {
357                 ERR("signal: SIGCHLD failed\n");
358                 return -1;
359         }
360
361         g_timeout_add_seconds(2, exit_server, NULL);
362
363         sig_reg = 1;
364         return 0;
365 }
366
367 static int __check_backend_status_for_exit(void)
368 {
369         int i = 0;
370         for(i = 0; i < num_of_backends; i++)
371         {
372                 if (!__is_backend_busy(i))
373                         continue;
374                 else
375                         return 0;
376         }
377         return 1;
378 }
379
380 static int __check_queue_status_for_exit(void)
381 {
382         pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
383         queue_info_map *ptr = NULL;
384         ptr = start;
385         int i = 0;
386         int c = 0;
387         int slot = -1;
388         for(i = 0; i < entries; i++)
389         {
390                 if (ptr->queue_slot <= slot) {
391                         ptr++;
392                         continue;
393                 }
394                 else {
395                         head[c] = ptr->head;
396                         slot = ptr->queue_slot;
397                         c++;
398                         ptr++;
399                 }
400         }
401         for(i = 0; i < num_of_backends; i++)
402         {
403                 if (!head[i])
404                         continue;
405                 else
406                         return 0;
407         }
408         return 1;
409 }
410
411 gboolean exit_server(void *data)
412 {
413         DBG("exit_server Start\n");
414         if (__check_backend_status_for_exit() &&
415                         __check_queue_status_for_exit()) {
416                 if (!getenv("PMS_STANDALONE")) {
417                         g_main_loop_quit(mainloop);
418                         return FALSE;
419                 }
420         }
421         return TRUE;
422 }
423
424 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
425 {
426         int fd;
427         int ret;
428         if (buf == NULL || path == NULL)
429                 return -1;
430         fd = open(path, O_RDONLY);
431         if (fd < 0)
432                 return -1;
433         ret = read(fd, buf, size - 1);
434         if (ret <= 0) {
435                 close(fd);
436                 return -1;
437         } else
438                 buf[ret] = 0;
439         close(fd);
440         return ret;
441 }
442
443 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
444                         const char *cmdline, const char *apppath)
445 {
446         int pid = 0;
447
448         if (strcmp(cmdline, apppath) == 0) {
449                 pid = atoi(dname);
450                 if (pid != getpgid(pid))
451                         pid = 0;
452         }
453         return pid;
454 }
455
456 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
457 {
458         DIR *dp;
459         struct dirent *dentry;
460         int pid;
461         int ret;
462         char buf[1024] = {'\0'};
463         int pgid;
464
465         dp = opendir("/proc");
466         if (dp == NULL) {
467                 return -1;
468         }
469
470         while ((dentry = readdir(dp)) != NULL) {
471                 if (!isdigit(dentry->d_name[0]))
472                         continue;
473
474                 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry->d_name);
475                 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
476                 if (ret <= 0)
477                         continue;
478
479                 pid = __pkgcmd_find_pid_by_cmdline(dentry->d_name, buf, apppath);
480                 if (pid > 0) {
481                         if (option == 0) {
482                                 closedir(dp);
483                                 return pid;
484                         }
485                         pgid = getpgid(pid);
486                         if (pgid <= 1) {
487                                 closedir(dp);
488                                 return -1;
489                         }
490                         if (killpg(pgid, SIGKILL) < 0) {
491                                 closedir(dp);
492                                 return -1;
493                         }
494                         closedir(dp);
495                         return pid;
496                 }
497         }
498         closedir(dp);
499         return 0;
500 }
501
502 static void __make_pid_info_file(char *req_key, int pid)
503 {
504         FILE* file;
505         int fd;
506         char buf[MAX_PKG_TYPE_LEN] = {0};
507         char info_file[PATH_MAX] = {'\0'};
508
509         if(req_key == NULL)
510                 return;
511
512         snprintf(info_file, PATH_MAX, "/tmp/pkgmgr/%s", req_key);
513
514         DBG("info_path(%s)", info_file);
515         file = fopen(info_file, "w");
516         if (file == NULL) {
517                 ERR("Couldn't open the file(%s)", info_file);
518                 return;
519         }
520
521         snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
522         fwrite(buf, 1, strlen(buf), file);
523
524         fflush(file);
525         fd = fileno(file);
526         fsync(fd);
527         fclose(file);
528 }
529
530 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
531 {
532         char *pkgid;
533         char *exec;
534         int ret;
535         int pid = -1;
536
537         if (handle == NULL) {
538                 perror("appinfo handle is NULL\n");
539                 exit(1);
540         }
541         ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
542         if (ret) {
543                 perror("Failed to get app exec path\n");
544                 exit(1);
545         }
546         ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
547         if (ret) {
548                 perror("Failed to get pkgid\n");
549                 exit(1);
550         }
551
552         if (strcmp(user_data, "kill") == 0)
553                 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
554         else if(strcmp(user_data, "check") == 0)
555                 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
556
557         __make_pid_info_file(pkgid, pid);
558
559         return 0;
560 }
561
562 void free_user_context(user_ctx* ctx)
563 {
564         char **env = NULL;
565         int i = 0;
566         if (!ctx)
567                 return;
568         env = ctx->env;
569         //env variable ends by NULL element
570         while (env[i]) {
571                 free(env[i]);
572                 i++;
573         }
574         free(env);
575         env = NULL;
576         free(ctx);
577 }
578
579 int set_environement(user_ctx *ctx)
580 {
581         int i = 0;
582         int res = 0;
583         char **env = NULL;
584         if (!ctx)
585                 return -1;;
586         if (setgid(ctx->gid)) {
587                 ERR("setgid failed: %d", errno);
588                 return -1;
589         }
590         if (setuid(ctx->uid)) {
591                 ERR("setuid failed: %d", errno);
592                 return -1;
593         }
594         env = ctx->env;
595         //env variable ends by NULL element
596         while (env[i]) {
597                 if (putenv(env[i]) != 0)
598                         res = -1;
599                 i++;
600         }
601         return res;
602 }
603
604 user_ctx *get_user_context(uid_t uid)
605 {
606         /* we can use getpwnam because this is used only after a
607          * fork and just before an execv
608          * No concurrencial call can corrupt the data
609          * returned by getpwuid
610          */
611         user_ctx *context_res;
612         char **env = NULL;
613         struct passwd *pwd;
614         int len;
615         int ret = 0;
616         int i;
617
618         pwd = getpwuid(uid);
619         if (!pwd)
620                 return NULL;
621
622         do {
623                 context_res = (user_ctx *)malloc(sizeof(user_ctx));
624                 if (!context_res) {
625                         ret = -1;
626                         break;
627                 }
628                 env = (char **)malloc(3 * sizeof(char *));
629                 if (!env) {
630                         ret = -1;
631                         break;
632                 }
633                 // Build environment context
634                 len = snprintf(NULL, 0, "HOME=%s", pwd->pw_dir);
635                 env[0] = (char *)malloc((len + 1) * sizeof(char));
636                 if(env[0] == NULL) {
637                         ret = -1;
638                         break;
639                 }
640                 snprintf(env[0], len + 1, "HOME=%s", pwd->pw_dir);
641                 len = snprintf(NULL, 0, "USER=%s", pwd->pw_name);
642                 env[1] = (char *)malloc((len + 1) * sizeof(char));
643                 if(env[1] == NULL) {
644                         ret = -1;
645                         break;
646                 }
647                 snprintf(env[1], len + 1, "USER=%s", pwd->pw_name);
648                 env[2] = NULL;
649         } while (0);
650
651         if (ret == -1) {
652                 free(context_res);
653                 context_res = NULL;
654                 i = 0;
655                 //env variable ends by NULL element
656                 while (env && env[i]) {
657                         free(env[i]);
658                         i++;
659                 }
660                 free(env);
661                 env = NULL;
662         } else {
663                 context_res->env = env;
664                 context_res->uid = uid;
665                 context_res->gid = pwd->pw_gid;
666         }
667         return context_res;
668 }
669
670 static char **__generate_argv(const char *args)
671 {
672         /* Create args vector
673          * req_id + pkgid + args
674          *
675          * vector size = # of args +
676          *(req_id + pkgid + NULL termination = 3)
677          * Last value must be NULL for execv.
678          */
679         gboolean ret_parse;
680         gint argcp;
681         gchar **argvp;
682         GError *gerr = NULL;
683         int i;
684
685         ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
686         if (FALSE == ret_parse) {
687                 DBG("Failed to split args: %s", args);
688                 DBG("messsage: %s", gerr->message);
689                 exit(1);
690         }
691
692         /* dbg */
693         for (i = 0; i < argcp; i++)
694                 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
695
696         return argvp;
697 }
698
699 void __set_environment(gpointer user_data)
700 {
701         user_ctx *ctx = (user_ctx *)user_data;
702
703         if (set_environement(ctx))
704                 DBG("Failed to set env for the user : %d", ctx->uid);
705 }
706
707 static int __fork_and_exec_with_args(char **argv, uid_t uid)
708 {
709         user_ctx* user_context;
710         GError *error = NULL;
711         gboolean ret;
712         int pid;
713
714         user_context = get_user_context(uid);
715         if (!user_context) {
716                 DBG("Failed to getenv for the user : %d", uid);
717                 return -1;
718         }
719
720         ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
721                         __set_environment, (gpointer)user_context, &pid,
722                         &error);
723         if (ret != TRUE) {
724                 ERR("Failed to excute backend: %s", error->message);
725                 g_error_free(error);
726         }
727
728         free_user_context(user_context);
729
730         return pid;
731 }
732
733 static int __change_item_info(pm_dbus_msg *item, uid_t uid)
734 {
735         int ret = 0;
736         char *pkgid = NULL;
737         bool is_global = false;
738         pkgmgrinfo_appinfo_h handle = NULL;
739
740         switch (item->req_type) {
741         case PKGMGR_REQUEST_TYPE_DISABLE_APP:
742         case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
743                 ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle);
744                 break;
745
746         case PKGMGR_REQUEST_TYPE_ENABLE_APP:
747         case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
748                 ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle);
749                 break;
750
751         default:
752                 return PMINFO_R_ERROR;
753         }
754
755         if (ret != PMINFO_R_OK)
756                 return PMINFO_R_ERROR;
757
758         ret = pkgmgrinfo_appinfo_is_global(handle, &is_global);
759         if (ret != PMINFO_R_OK)
760                 goto catch;
761
762         if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_APP
763                         || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_APP)
764                         && is_global) {
765                         ret = PMINFO_R_ERROR;
766                         goto catch;
767         } else if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID
768                         || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
769                         && !is_global) {
770                         ret = PMINFO_R_ERROR;
771                         goto catch;
772         }
773
774         ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
775         if (ret != PMINFO_R_OK)
776                 goto catch;
777
778         strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1);
779         memset((item->pkgid),0,MAX_PKG_NAME_LEN);
780         strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
781
782 catch:
783         pkgmgrinfo_appinfo_destroy_appinfo(handle);
784
785         return ret;
786 }
787
788 static int __process_install(pm_dbus_msg *item)
789 {
790         char *backend_cmd;
791         char **argv;
792         char args[MAX_PKG_ARGS_LEN] = {'\0', };
793         int pid;
794
795         backend_cmd = _get_backend_cmd(item->pkg_type);
796         if (backend_cmd == NULL)
797                 return -1;
798
799         snprintf(args, sizeof(args), "%s -k %s -i %s %s", backend_cmd,
800                         item->req_id, item->pkgid, item->args);
801
802         argv = __generate_argv(args);
803
804         pid = __fork_and_exec_with_args(argv, item->uid);
805         g_strfreev(argv);
806         free(backend_cmd);
807
808         return pid;
809 }
810
811 static int __process_reinstall(pm_dbus_msg *item)
812 {
813         char *backend_cmd;
814         char **argv;
815         char args[MAX_PKG_ARGS_LEN];
816         int pid;
817
818         backend_cmd = _get_backend_cmd(item->pkg_type);
819         if (backend_cmd == NULL)
820                 return -1;
821
822         snprintf(args, sizeof(args), "%s -k %s -r %s", backend_cmd,
823                         item->req_id, item->pkgid);
824         argv = __generate_argv(args);
825
826         pid = __fork_and_exec_with_args(argv, item->uid);
827
828         g_strfreev(argv);
829         free(backend_cmd);
830
831         return pid;
832 }
833
834 static int __process_uninstall(pm_dbus_msg *item)
835 {
836         char *backend_cmd;
837         char **argv;
838         char args[MAX_PKG_ARGS_LEN];
839         int pid;
840
841         backend_cmd = _get_backend_cmd(item->pkg_type);
842         if (backend_cmd == NULL)
843                 return -1;
844
845         snprintf(args, sizeof(args), "%s -k %s -d %s", backend_cmd,
846                         item->req_id, item->pkgid);
847         argv = __generate_argv(args);
848
849         pid = __fork_and_exec_with_args(argv, item->uid);
850
851         g_strfreev(argv);
852         free(backend_cmd);
853
854         return pid;
855 }
856
857 static int __process_move(pm_dbus_msg *item)
858 {
859         char *backend_cmd;
860         char **argv;
861         char args[MAX_PKG_ARGS_LEN];
862         int pid;
863
864         backend_cmd = _get_backend_cmd(item->pkg_type);
865         if (backend_cmd == NULL)
866                 return -1;
867
868         /* TODO: set movetype */
869         snprintf(args, sizeof(args), "%s -k %s -m %s -t %s", backend_cmd,
870                         item->req_id, item->pkgid, item->args);
871         argv = __generate_argv(args);
872
873         pid = __fork_and_exec_with_args(argv, item->uid);
874
875         g_strfreev(argv);
876         free(backend_cmd);
877
878         return pid;
879 }
880
881 static int __process_enable_pkg(pm_dbus_msg *item)
882 {
883         /* TODO */
884         return 0;
885 }
886
887 static int __process_disable_pkg(pm_dbus_msg *item)
888 {
889         /* TODO */
890         return 0;
891 }
892
893 static int __process_enable_app(pm_dbus_msg *item)
894 {
895         int ret = -1;
896
897         __send_app_signal(item->uid, item->req_id, item->pkg_type,
898                         item->pkgid, item->pkgid,
899                         PKGMGR_INSTALLER_START_KEY_STR,
900                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR);
901
902         /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
903         ret = __change_item_info(item, item->uid);
904         if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
905                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
906                                 item->pkgid, item->pkgid,
907                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
908                 return ret;
909         }
910
911         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 0);
912         if (ret != PMINFO_R_OK)
913                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
914                                 item->pkgid, item->appid,
915                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
916         else
917                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
918                                 item->pkgid, item->appid,
919                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
920
921         return ret;
922 }
923
924 static int __process_disable_app(pm_dbus_msg *item)
925 {
926         int ret = -1;
927
928         __send_app_signal(item->uid, item->req_id, item->pkg_type,
929                         item->pkgid, item->pkgid,
930                         PKGMGR_INSTALLER_START_KEY_STR,
931                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR);
932
933         /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
934         ret = __change_item_info(item, item->uid);
935         if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
936                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
937                                 item->pkgid, item->pkgid,
938                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
939                 return ret;
940         }
941
942         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1);
943         if (ret != PMINFO_R_OK)
944                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
945                                 item->pkgid, item->appid,
946                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
947         else
948                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
949                                 item->pkgid, item->appid,
950                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
951
952         return ret;
953 }
954
955 static int __process_enable_global_app_for_uid(pm_dbus_msg *item)
956 {
957         int ret = -1;
958
959         __send_app_signal(item->uid, item->req_id, item->pkg_type,
960                         item->pkgid, item->pkgid,
961                         PKGMGR_INSTALLER_START_KEY_STR,
962                         PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID);
963
964         /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
965         ret = __change_item_info(item, item->uid);
966         if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
967                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
968                                 item->pkgid, item->pkgid,
969                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
970                 return ret;
971         }
972
973         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0);
974         if (ret != PMINFO_R_OK)
975                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
976                                 item->pkgid, item->appid,
977                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
978         else
979                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
980                                 item->pkgid, item->appid,
981                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
982
983         return ret;
984 }
985
986 static int __process_disable_global_app_for_uid(pm_dbus_msg *item)
987 {
988         int ret = -1;
989
990         __send_app_signal(item->uid, item->req_id, item->pkg_type,
991                         item->pkgid, item->pkgid,
992                         PKGMGR_INSTALLER_START_KEY_STR,
993                         PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID);
994
995         /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
996         ret = __change_item_info(item, GLOBAL_USER);
997         if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
998                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
999                                 item->pkgid, item->pkgid,
1000                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
1001                 return ret;
1002         }
1003
1004         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 1);
1005         if (ret != PMINFO_R_OK)
1006                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1007                                 item->pkgid, item->appid,
1008                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
1009         else
1010                 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1011                                 item->pkgid, item->appid,
1012                                 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
1013
1014         return ret;
1015 }
1016
1017 static int __process_getsize(pm_dbus_msg *item)
1018 {
1019         static const char *backend_cmd = "/usr/bin/pkg_getsize";
1020         char **argv;
1021         char args[MAX_PKG_ARGS_LEN];
1022         int pid;
1023
1024         snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid,
1025                         item->args, item->req_id);
1026         argv = __generate_argv(args);
1027         pid = __fork_and_exec_with_args(argv, item->uid);
1028
1029         g_strfreev(argv);
1030
1031         return pid;
1032 }
1033
1034 static int __process_cleardata(pm_dbus_msg *item)
1035 {
1036         char *backend_cmd;
1037         char **argv;
1038         char args[MAX_PKG_ARGS_LEN];
1039         int pid;
1040
1041         backend_cmd = _get_backend_cmd(item->pkg_type);
1042         if (backend_cmd == NULL)
1043                 return -1;
1044
1045         /* TODO: set movetype */
1046         snprintf(args, sizeof(args), "%s -k %s -c %s", backend_cmd,
1047                         item->req_id, item->pkgid);
1048         argv = __generate_argv(args);
1049
1050         pid = __fork_and_exec_with_args(argv, item->uid);
1051
1052         g_strfreev(argv);
1053         free(backend_cmd);
1054
1055         return pid;
1056 }
1057
1058 static int __process_clearcache(pm_dbus_msg *item)
1059 {
1060         static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1061         char **argv;
1062         char args[MAX_PKG_ARGS_LEN];
1063         int pid;
1064
1065         snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid);
1066         argv = __generate_argv(args);
1067         pid = __fork_and_exec_with_args(argv, item->uid);
1068
1069         g_strfreev(argv);
1070
1071         return pid;
1072 }
1073
1074 static int __process_kill(pm_dbus_msg *item)
1075 {
1076         int ret;
1077         pkgmgrinfo_pkginfo_h handle;
1078
1079         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1080                         &handle);
1081         if (ret < 0) {
1082                 ERR("Failed to get handle");
1083                 return -1;
1084         }
1085
1086         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1087                         __pkgcmd_app_cb, "kill", item->uid);
1088         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1089         if (ret < 0) {
1090                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1091                 return -1;
1092         }
1093
1094         return 0;
1095 }
1096
1097 static int __process_check(pm_dbus_msg *item)
1098 {
1099         int ret;
1100         pkgmgrinfo_pkginfo_h handle;
1101
1102         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1103                         &handle);
1104         if (ret < 0) {
1105                 ERR("Failed to get handle");
1106                 return -1;
1107         }
1108
1109         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1110                         __pkgcmd_app_cb, "check", item->uid);
1111         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1112         if (ret < 0) {
1113                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1114                 return -1;
1115         }
1116
1117         return 0;
1118 }
1119
1120 static int __process_generate_license_request(pm_dbus_msg *item)
1121 {
1122         int ret;
1123         char *resp_data;
1124         char req_data[MAX_PKG_ARGS_LEN];
1125         unsigned int req_data_len;
1126         char license_url[MAX_PKG_ARGS_LEN];
1127         unsigned int license_url_len;
1128
1129         resp_data = item->args;
1130         req_data_len = sizeof(req_data);
1131         license_url_len = sizeof(license_url);
1132
1133         ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1134                         req_data, &req_data_len, license_url, &license_url_len);
1135         if (ret != TADC_SUCCESS) {
1136                 ERR("drm_tizen_generate_license_request failed: %d", ret);
1137                 __return_value_to_caller(item->req_id, g_variant_new("(iss)",
1138                                         PKGMGR_R_ESYSTEM, "", ""));
1139                 return -1;
1140         }
1141
1142         __return_value_to_caller(item->req_id,
1143                         g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1144                                 license_url));
1145
1146         return 0;
1147 }
1148
1149 static int __process_register_license(pm_dbus_msg *item)
1150 {
1151         int ret;
1152         char *resp_data;
1153
1154         resp_data = item->args;
1155
1156         ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1157         if (ret != TADC_SUCCESS) {
1158                 ERR("drm_tizen_register_license failed: %d", ret);
1159                 __return_value_to_caller(item->req_id,
1160                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1161                 return -1;
1162         }
1163
1164         __return_value_to_caller(item->req_id,
1165                         g_variant_new("(i)", PKGMGR_R_OK));
1166
1167         return 0;
1168 }
1169
1170 static int __process_decrypt_package(pm_dbus_msg *item)
1171 {
1172         int ret;
1173         char *drm_file_path;
1174         char *decrypted_file_path;
1175
1176         drm_file_path = item->pkgid;
1177         decrypted_file_path = item->args;
1178
1179         /* TODO: check ownership of decrypted file */
1180         ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1181                         decrypted_file_path, strlen(decrypted_file_path));
1182         if (ret != TADC_SUCCESS) {
1183                 ERR("drm_tizen_register_license failed: %d", ret);
1184                 __return_value_to_caller(item->req_id,
1185                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1186                 return -1;
1187         }
1188
1189         __return_value_to_caller(item->req_id,
1190                         g_variant_new("(i)", PKGMGR_R_OK));
1191
1192         return 0;
1193 }
1194
1195 static int __process_add_blacklist(pm_dbus_msg *item)
1196 {
1197         int ret;
1198
1199         ret = __add_blacklist(item->uid, item->pkgid);
1200
1201         __return_value_to_caller(item->req_id,
1202                         g_variant_new("(i)", ret));
1203
1204         return ret;
1205 }
1206
1207 static int __process_remove_blacklist(pm_dbus_msg *item)
1208 {
1209         int ret;
1210
1211         ret = __remove_blacklist(item->uid, item->pkgid);
1212
1213         __return_value_to_caller(item->req_id,
1214                         g_variant_new("(i)", ret));
1215
1216         return ret;
1217 }
1218
1219 static int __process_check_blacklist(pm_dbus_msg *item)
1220 {
1221         int ret;
1222         int result = 0;
1223
1224         ret = __check_blacklist(item->uid, item->pkgid, &result);
1225
1226         __return_value_to_caller(item->req_id,
1227                         g_variant_new("(ii)", result, ret));
1228
1229         return ret;
1230 }
1231
1232 gboolean queue_job(void *data)
1233 {
1234         pm_dbus_msg *item = NULL;
1235         backend_info *ptr;
1236         int x;
1237         int ret;
1238
1239         /* Pop a job from queue */
1240         for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1241                 if (__is_backend_busy(x))
1242                         continue;
1243
1244                 item = _pm_queue_pop(x);
1245                 if (item && item->req_type != -1)
1246                         break;
1247                 free(item);
1248         }
1249
1250         /* all backend messages queue are empty or busy */
1251         if (x == num_of_backends)
1252                 return FALSE;
1253
1254         /*save pkg type and pkg name for future*/
1255         strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
1256         strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
1257         strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN-1);
1258         memset((item->appid),0,MAX_PKG_NAME_LEN);
1259         ptr->uid = item->uid;
1260         DBG("handle request type [%d]", item->req_type);
1261
1262         switch (item->req_type) {
1263         case PKGMGR_REQUEST_TYPE_INSTALL:
1264                 __set_backend_busy(x);
1265                 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1266                 ret = __process_install(item);
1267                 break;
1268         case PKGMGR_REQUEST_TYPE_REINSTALL:
1269                 __set_backend_busy(x);
1270                 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1271                 ret = __process_reinstall(item);
1272                 break;
1273         case PKGMGR_REQUEST_TYPE_UNINSTALL:
1274                 __set_backend_busy(x);
1275                 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1276                 ret = __process_uninstall(item);
1277                 break;
1278         case PKGMGR_REQUEST_TYPE_MOVE:
1279                 __set_backend_busy(x);
1280                 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1281                 ret = __process_move(item);
1282                 break;
1283         case PKGMGR_REQUEST_TYPE_ENABLE_PKG:
1284                 ret = __process_enable_pkg(item);
1285                 break;
1286         case PKGMGR_REQUEST_TYPE_DISABLE_PKG:
1287                 ret = __process_disable_pkg(item);
1288                 break;
1289         case PKGMGR_REQUEST_TYPE_ENABLE_APP:
1290                 ret = __process_enable_app(item);
1291                 break;
1292         case PKGMGR_REQUEST_TYPE_DISABLE_APP:
1293                 ret = __process_disable_app(item);
1294                 break;
1295         case PKGMGR_REQUEST_TYPE_GETSIZE:
1296                 __set_backend_busy(x);
1297                 ret = __process_getsize(item);
1298                 break;
1299         case PKGMGR_REQUEST_TYPE_CLEARDATA:
1300                 __set_backend_busy(x);
1301                 ret = __process_cleardata(item);
1302                 break;
1303         case PKGMGR_REQUEST_TYPE_CLEARCACHE:
1304                 __set_backend_busy(x);
1305                 ret = __process_clearcache(item);
1306                 break;
1307         case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1308                 ret = __process_enable_global_app_for_uid(item);
1309                 break;
1310         case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1311                 ret = __process_disable_global_app_for_uid(item);
1312                 break;
1313         case PKGMGR_REQUEST_TYPE_KILL:
1314                 ret = __process_kill(item);
1315                 break;
1316         case PKGMGR_REQUEST_TYPE_CHECK:
1317                 ret = __process_check(item);
1318                 break;
1319         case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1320                 ret = __process_generate_license_request(item);
1321                 break;
1322         case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE:
1323                 ret = __process_register_license(item);
1324                 break;
1325         case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE:
1326                 ret = __process_decrypt_package(item);
1327                 break;
1328         case PKGMGR_REQUEST_TYPE_ADD_BLACKLIST:
1329                 ret = __process_add_blacklist(item);
1330                 break;
1331         case PKGMGR_REQUEST_TYPE_REMOVE_BLACKLIST:
1332                 ret = __process_remove_blacklist(item);
1333                 break;
1334         case PKGMGR_REQUEST_TYPE_CHECK_BLACKLIST:
1335                 ret = __process_check_blacklist(item);
1336                 break;
1337         default:
1338                 ret = -1;
1339                 break;
1340         }
1341
1342         ptr->pid = ret;
1343         free(item);
1344
1345         return FALSE;
1346 }
1347
1348 #define IS_WHITESPACE(CHAR) \
1349 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1350
1351 void _app_str_trim(char *input)
1352 {
1353         char *trim_str = input;
1354
1355         if (input == NULL)
1356                 return;
1357
1358         while (*input != 0) {
1359                 if (!IS_WHITESPACE(*input)) {
1360                         *trim_str = *input;
1361                         trim_str++;
1362                 }
1363                 input++;
1364         }
1365
1366         *trim_str = 0;
1367         return;
1368 }
1369
1370 char *_get_backend_cmd(char *type)
1371 {
1372         FILE *fp = NULL;
1373         char buffer[1024] = { 0 };
1374         char *command = NULL;
1375         int size = 0;
1376         fp = fopen(PKG_CONF_PATH, "r");
1377         if (fp == NULL) {
1378                 return NULL;
1379         }
1380
1381         char *path = NULL;
1382         while (fgets(buffer, 1024, fp) != NULL) {
1383                 if (buffer[0] == '#')
1384                         continue;
1385
1386                 _app_str_trim(buffer);
1387
1388                 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1389                         DBG("buffer [%s]", buffer);
1390                         path = path + strlen(PKG_BACKEND);
1391                         DBG("path [%s]", path);
1392
1393                         command =
1394                             (char *)malloc(sizeof(char) * strlen(path) +
1395                                            strlen(type) + 1);
1396                         if (command == NULL) {
1397                                 fclose(fp);
1398                                 return NULL;
1399                         }
1400
1401                         size = strlen(path) + strlen(type) + 1;
1402                         snprintf(command, size, "%s%s", path, type);
1403                         command[strlen(path) + strlen(type)] = '\0';
1404                         DBG("command [%s]", command);
1405
1406                         if (fp != NULL)
1407                                 fclose(fp);
1408
1409                         return command;
1410                 }
1411
1412                 memset(buffer, 0x00, 1024);
1413         }
1414
1415         if (fp != NULL)
1416                 fclose(fp);
1417
1418         return NULL;            /* cannot find proper command */
1419 }
1420
1421 int main(int argc, char *argv[])
1422 {
1423         FILE *fp_status = NULL;
1424         char buf[32] = { 0, };
1425         pid_t pid;
1426         char *backend_cmd = NULL;
1427         char *backend_name = NULL;
1428         int r;
1429
1430         DBG("server start");
1431
1432         if (argv[1] && (strcmp(argv[1], "init") == 0)) {
1433                 /* if current status is "processing",
1434                    execute related backend with '-r' option */
1435                 if (!(fp_status = fopen(STATUS_FILE, "r")))
1436                         return 0;       /*if file is not exist, terminated. */
1437                 /* if processing <-- unintended termination */
1438                 if (fgets(buf, 32, fp_status) &&
1439                                 strcmp(buf, "processing") == 0) {
1440                         pid = fork();
1441                         if (pid == 0) { /* child */
1442                                 if (fgets(buf, 32, fp_status))
1443                                         backend_cmd = _get_backend_cmd(buf);
1444                                 if (!backend_cmd) {     /* if NULL, */
1445                                         DBG("fail to get backend command");
1446                                         goto err;
1447                                 }
1448                                 backend_name =
1449                                         strrchr(backend_cmd, '/');
1450                                 if (!backend_name) {
1451                                         DBG("fail to get backend name");
1452                                         goto err;
1453                                 }
1454
1455                                 execl(backend_cmd, backend_name, "-r",
1456                                                 NULL);
1457                                 if (backend_cmd)
1458                                         free(backend_cmd);
1459                                 fprintf(fp_status, " ");
1460 err:
1461                                 fclose(fp_status);
1462                                 exit(13);
1463                         } else if (pid < 0) {   /* error */
1464                                 DBG("fork fail");
1465                                 fclose(fp_status);
1466                                 return 0;
1467                         } else {        /* parent */
1468
1469                                 DBG("parent end\n");
1470                                 fprintf(fp_status, " ");
1471                                 fclose(fp_status);
1472                                 return 0;
1473                         }
1474                 }
1475         }
1476
1477         r = _pm_queue_init();
1478         if (r) {
1479                 DBG("Queue Initialization Failed\n");
1480                 return -1;
1481         }
1482
1483         r = __init_backend_info();
1484         if (r) {
1485                 DBG("backend info init failed");
1486                 return -1;
1487         }
1488
1489         r = __init_request_handler();
1490         if (r) {
1491                 ERR("dbus init failed");
1492                 return -1;
1493         }
1494
1495         if (__register_signal_handler()) {
1496                 ERR("failed to register signal handler");
1497                 return -1;
1498         }
1499
1500 #if !GLIB_CHECK_VERSION(2,35,0)
1501         g_type_init();
1502 #endif
1503         mainloop = g_main_loop_new(NULL, FALSE);
1504         if (!mainloop) {
1505                 ERR("g_main_loop_new failed");
1506                 return -1;
1507         }
1508
1509         DBG("Main loop is created.");
1510
1511         g_main_loop_run(mainloop);
1512
1513         DBG("Quit main loop.");
1514         __fini_request_handler();
1515         __fini_backend_info();
1516         _pm_queue_final();
1517
1518         DBG("package manager server terminated.");
1519
1520         return 0;
1521 }