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