Fixed Prevent Issues. CID 49075, 44391
[framework/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 <unistd.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <sys/inotify.h>
30 #include <sys/stat.h>
31 #include <sys/ioctl.h>
32 #include <fcntl.h>
33 #include <glib.h>
34 #include <signal.h>
35 #include <Elementary.h>
36 #include <appcore-efl.h>
37 #include <Ecore_X.h>
38 #include <Ecore_File.h>
39 #include <ail.h>
40 #include <pkgmgr-info.h>
41
42 #include <X11/Xatom.h>
43 #include <X11/Xutil.h>
44
45 #include "pkgmgr_installer.h"
46 #include "comm_pkg_mgr_server.h"
47 #include "pkgmgr-server.h"
48 #include "pm-queue.h"
49 #include "comm_config.h"
50
51 /* debug output */
52 #if defined(NDEBUG)
53 #define DBG(fmt, args...)
54 #define __SET_DBG_OUTPUT(fp)
55 #elif defined(PRINT)
56 #include <stdio.h>
57 FILE *___log = NULL;
58 #define DBG(fmt, args...) \
59         {if (!___log) ___log = stderr; \
60          fprintf(___log, "[DBG:PMS]%s:%d:%s(): " fmt "\n",\
61          basename(__FILE__), __LINE__, __func__, ##args); fflush(___log); }
62 #define __SET_DBG_OUTPUT(fp) \
63         (___log = fp)
64 #else
65 #include <dlog.h>
66 #undef LOG_TAG
67 #define LOG_TAG "PKGMGR_SERVER"
68
69 #define DBGE(fmt, arg...) LOGE(fmt,##arg)
70 #define DBG(fmt, arg...) LOGD(fmt,##arg)
71 #endif
72
73 #if !defined(PACKAGE)
74 #define PACKAGE "package-manager"
75 #endif
76
77 #if !defined(LOCALEDIR)
78 #define LOCALEDIR "/usr/share/locale"
79 #endif
80
81 #define DESKTOP_W   720.0
82
83 #define NO_MATCHING_FILE 11
84
85 static int backend_flag = 0;    /* 0 means that backend process is not running */
86 static int drawing_popup = 0;   /* 0 means that pkgmgr-server has no popup now */
87
88 /* For pkgs with no desktop file, inotify callback wont be called.
89 *  To handle that case ail_db_update is initialized as 1
90 *  This flag will be used to ensure that pkgmgr server does not exit
91 *  before the db is updated. */
92 int ail_db_update = 1;
93
94 /*
95 8 bit value to represent maximum 8 backends.
96 Each bit position corresponds to a queue slot which
97 is dynamically determined.
98 */
99 char backend_busy = 0;
100 /*
101 8 bit value to represent quiet mode operation for maximum 8 backends
102 1->quiet 0->non-quiet
103 Each bit position corresponds to a queue slot which
104 is dynamically determined.
105 */
106 char backend_mode = 63; /*00111111*/
107 extern int num_of_backends;
108
109 backend_info *begin;
110 extern queue_info_map *start;
111 extern int entries;
112 int pos = 0;
113 /*To store info in case of backend crash*/
114 char pname[MAX_PKG_NAME_LEN] = {'\0'};
115 char ptype[MAX_PKG_TYPE_LEN] = {'\0'};
116 char args[MAX_PKG_ARGS_LEN] = {'\0'};
117
118 GMainLoop *mainloop = NULL;
119
120
121 /* operation_type */
122 typedef enum {
123         OPERATION_INSTALL = 0,
124         OPERATION_UNINSTALL,
125         OPERATION_ACTIVATE,
126         OPERATION_REINSTALL,
127         OPERATION_MAX
128 } OPERATION_TYPE;
129
130 struct appdata {
131         Evas_Object *win;
132         Evas_Object *notify;
133         pm_dbus_msg *item;
134         OPERATION_TYPE op_type;
135 };
136
137 struct pm_desktop_notifier_t {
138         int ifd;
139         Ecore_Fd_Handler *handler;
140 };
141 typedef struct pm_desktop_notifier_t pm_desktop_notifier;
142
143 pm_desktop_notifier desktop_notifier;
144 pm_inotify_paths paths[DESKTOP_FILE_DIRS_NUM];
145 static int __check_backend_status_for_exit();
146 static int __check_queue_status_for_exit();
147 static int __check_backend_mode();
148 static int __is_backend_busy(int position);
149 static void __set_backend_busy(int position);
150 static void __set_backend_free(int position);
151 static int __is_backend_mode_quiet(int position);
152 static void __set_backend_mode(int position);
153 static void __unset_backend_mode(int position);
154 static void response_cb1(void *data, Evas_Object *notify, void *event_info);
155 static void response_cb2(void *data, Evas_Object *notify, void *event_info);
156 static int create_popup(struct appdata *ad);
157 static void sighandler(int signo);
158 static int __get_position_from_pkg_type(char *pkgtype);
159 static int __is_efl_tpk_app(char *pkgpath);
160 static int __xsystem(const char *argv[]);
161
162 gboolean queue_job(void *data);
163 gboolean send_fail_signal(void *data);
164 gboolean exit_server(void *data);
165 static Eina_Bool __directory_notify(void *data, Ecore_Fd_Handler *fd_handler);
166
167 /* To check whether a particular backend is free/busy*/
168 static int __is_backend_busy(int position)
169 {
170         return backend_busy & 1<<position;
171 }
172 /*To set a particular backend as busy*/
173 static void __set_backend_busy(int position)
174 {
175         backend_busy = backend_busy | 1<<position;
176 }
177 /*To set a particular backend as free */
178 static void __set_backend_free(int position)
179 {
180         backend_busy = backend_busy & ~(1<<position);
181 }
182 /* To check whether a particular backend is running in quiet mode*/
183 static int __is_backend_mode_quiet(int position)
184 {
185         return backend_mode & 1<<position;
186 }
187 /*To set a particular backend mode as quiet*/
188 static void __set_backend_mode(int position)
189 {
190         backend_mode = backend_mode | 1<<position;
191 }
192 /*To unset a particular backend mode */
193 static void __unset_backend_mode(int position)
194 {
195         backend_mode = backend_mode & ~(1<<position);
196 }
197
198 static int __get_position_from_pkg_type(char *pkgtype)
199 {
200         int i = 0;
201         queue_info_map *ptr;
202         ptr = start;
203         for(i = 0; i < entries; i++)
204         {
205                 if (!strncmp(ptr->pkgtype, pkgtype, MAX_PKG_TYPE_LEN))
206                         return ptr->queue_slot;
207                 else
208                         ptr++;
209
210         }
211         return -1;
212 }
213
214 static int __xsystem(const char *argv[])
215 {
216         int err = 0;
217         int status = 0;
218         pid_t pid;
219
220         pid = fork();
221
222         switch (pid) {
223         case -1:
224                 DBG("fork() failed");
225                 return -1;
226         case 0:
227                 if (execvp(argv[0], (char *const *)argv) == -1) {
228                         DBG("execvp() failed");
229                 }
230                 _exit(100);
231         default:
232                 /* parent */
233                 do {
234                         err = waitpid(pid, &status, WUNTRACED | WCONTINUED);
235                         if (err == -1) {
236                                 DBG("waitpid failed\n");
237                                 return -1;
238                         }
239                 } while (!WIFEXITED(status) && !WIFSIGNALED(status));
240                 break;
241         }
242         if (WIFEXITED(status))
243                 return WEXITSTATUS(status);
244         else
245                 return -1;
246 }
247
248 static int __is_efl_tpk_app(char *pkgid)
249 {
250         int ret = 0;
251         char *type = NULL;
252         const char *unzip_argv[] = { "/usr/bin/unzip", "-j", pkgid, "usr/share/packages/*", "-d", "/tmp/efltpk-unzip", NULL };
253         const char *unzip_opt_argv[] = { "/usr/bin/unzip", "-j", pkgid, "opt/share/packages/*", "-d", "/tmp/efltpk-unzip", NULL };
254         const char *delete_argv[] = { "/bin/rm", "-rf", "/tmp/efltpk-unzip", NULL };
255         pkgmgrinfo_pkginfo_h handle;
256         /*Check for uninstall case. If we fail to get handle then request is for installation*/
257         ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
258         if (ret == PMINFO_R_OK) {
259                 ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
260                 if (ret != PMINFO_R_OK) {
261                         DBG("Failed to get package type\n");
262                         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
263                         return -1;
264                 }
265                 if (strcmp(type, "efltpk") == 0) {
266                         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
267                         return 1;
268                 } else {
269                         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
270                         return 0;
271                 }
272         }
273         /*Install request*/
274         if (strstr(pkgid, ".tpk") == NULL) {
275                 DBG("TPK package");
276                 return 0;
277         }
278         __xsystem(delete_argv);
279         ret = mkdir("/tmp/efltpk-unzip", 0755);
280         if (ret != 0) {
281                 DBG("Failed to create temporary directory to unzip tpk package\n");
282                 return -1;
283         }
284         /*In case of installation request, pkgid contains the pkgpath*/
285         ret = __xsystem(unzip_argv);
286         if (ret) {
287                 ret = __xsystem(unzip_opt_argv);
288                 if (ret) {
289                         DBG("Unzip of tpk package failed. error:%d\n", ret);
290                         if (ret == NO_MATCHING_FILE) /*no matching file found*/
291                                 ret = 0;
292                         else
293                                 ret = -1;
294                         goto err;
295                 } else
296                         ret = 1;
297         } else
298                 ret = 1;
299 err:
300         __xsystem(delete_argv);
301         return ret;
302 }
303
304
305 static Eina_Bool __directory_notify(void *data, Ecore_Fd_Handler *fd_handler)
306 {
307         ail_db_update = 0;
308         char *buf = NULL;
309         ssize_t read_size = 0;
310         ssize_t len = 0;
311         ssize_t i = 0;
312         int fd = -1;
313
314         fd = ecore_main_fd_handler_fd_get(fd_handler);
315         DBG("ifd [%d]\n", fd);
316
317         if (ioctl(fd, FIONREAD, &read_size) < 0) {
318                 DBG("Failed to get byte size\n");
319                 ail_db_update = 1;
320                 return ECORE_CALLBACK_CANCEL;
321         }
322
323         if (read_size <= 0) {
324                 DBG("Buffer is not ready!!!\n");
325                 ail_db_update = 1;
326                 return ECORE_CALLBACK_RENEW;
327         }
328
329         buf = calloc(1, read_size+1);
330         if (!buf) {
331                 DBG("Failed to allocate memory for event handling\n");
332                 ail_db_update = 1;
333                 return ECORE_CALLBACK_RENEW;
334         }
335
336         len = read(fd, buf, read_size);
337         if (len < 0) {
338                 free(buf);
339                 /*Stop monitoring about this invalid file descriptor */
340                 ail_db_update = 1;
341                 return ECORE_CALLBACK_CANCEL;
342         }
343
344         buf[len] = 0;
345
346         while (i < len) {
347                 struct inotify_event *event = (struct inotify_event*) &buf[i];
348                 char *str_potksed = "potksed.";
349                 char *cut;
350                 char *package = NULL;
351                 ssize_t idx;
352                 int nev_name;
353
354                 /* 1. check the extension of a file */
355                 nev_name = strlen(event->name) - 1;
356                 for (idx = 0; nev_name >= 0 && str_potksed[idx]; idx++) {
357                         if (event->name[nev_name] != str_potksed[idx]) {
358                                 break;
359                         }
360                         nev_name --;
361                 }
362
363                 if (str_potksed[idx] != '\0') {
364                         DBG("This is not a desktop file : %s\n", event->name);
365                         i += sizeof(struct inotify_event) + event->len;
366                         continue;
367                 }
368
369                 package = strdup(event->name);
370                 if (package == NULL)
371                         continue;
372
373                 cut = strstr(package, ".desktop");
374                 if (cut)
375                         *cut = '\0';
376                 DBG("Package : %s\n", package);
377
378                 /* add & update */
379                 if (event->mask & IN_CLOSE_WRITE || event->mask & IN_MOVED_TO) {
380                         ail_appinfo_h ai = NULL;
381                         ail_error_e ret;
382
383                         ret = ail_package_get_appinfo(package, &ai);
384                         if (ai)
385                                 ail_package_destroy_appinfo(ai);
386
387                         if (AIL_ERROR_NO_DATA == ret) {
388                                 if (ail_desktop_add(package) < 0) {
389                                         DBG("Failed to add a new package (%s)\n", event->name);
390                                 }
391                         } else if (AIL_ERROR_OK == ret) {
392                                 if (ail_desktop_update(package) < 0) {
393                                         DBG("Failed to add a new package (%s)\n", event->name);
394                                 }
395                         } else;
396                         /* delete */
397                 } else if (event->mask & IN_DELETE) {
398                         if (ail_desktop_remove(package) < 0)
399                                 DBG("Failed to remove a package (%s)\n",
400                                     event->name);
401                 } else {
402                         DBG("this event is not dealt with inotify\n");
403                 }
404
405                 free(package);
406
407                 i += sizeof(struct inotify_event) + event->len;
408         }
409
410         free(buf);
411         ail_db_update = 1;
412         return ECORE_CALLBACK_RENEW;
413 }
414
415 static
416 void response_cb1(void *data, Evas_Object *notify, void *event_info)
417 {
418         struct appdata *ad = (struct appdata *)data;
419         int p = 0;
420         int ret = 0;
421         DBG("start of response_cb()\n");
422
423         /* YES  */
424         DBG("Uninstalling... [%s]\n", ad->item->pkgid);
425
426         if (strlen(ad->item->pkgid) == 0) {
427                 DBG("package_name is empty\n");
428         }
429
430         if (strlen(ad->item->pkg_type) == 0) {
431                 DBG("Fail :  Uninstalling... [%s]\n",
432                     ad->item->pkgid);
433                 free(ad->item);
434                 evas_object_del(ad->notify);
435                 evas_object_del(ad->win);
436                 drawing_popup = 0;
437
438                 return;
439         }
440
441         DBG("pkg_type = [%s]\n", ad->item->pkg_type);
442
443         ret = _pm_queue_push(ad->item);
444         p = __get_position_from_pkg_type(ad->item->pkg_type);
445         __unset_backend_mode(p);
446
447         /* Free resource */
448         free(ad->item);
449         evas_object_del(ad->notify);
450         evas_object_del(ad->win);
451         /***************/
452         if (ret == 0)
453                 g_idle_add(queue_job, NULL);
454
455         DBG("end of response_cb()\n");
456
457         drawing_popup = 0;
458
459         return;
460 }
461
462 static
463 void response_cb2(void *data, Evas_Object *notify, void *event_info)
464 {
465         int p = 0;
466         struct appdata *ad = (struct appdata *)data;
467
468         DBG("start of response_cb()\n");
469
470         /* NO  */
471         pkgmgr_installer *pi;
472         gboolean ret_parse;
473         gint argcp;
474         gchar **argvp;
475         GError *gerr = NULL;
476
477         pi = pkgmgr_installer_new();
478         if (!pi) {
479                 DBG("Failure in creating the pkgmgr_installer object");
480                 return;
481         }
482
483         ret_parse = g_shell_parse_argv(ad->item->args,
484                                        &argcp, &argvp, &gerr);
485         if (FALSE == ret_parse) {
486                 DBG("Failed to split args: %s", ad->item->args);
487                 DBG("messsage: %s", gerr->message);
488                 pkgmgr_installer_free(pi);
489                 return;
490         }
491
492         pkgmgr_installer_receive_request(pi, argcp, argvp);
493
494         pkgmgr_installer_send_signal(pi, ad->item->pkg_type,
495                                      ad->item->pkgid, "end",
496                                      "cancel");
497
498         pkgmgr_installer_free(pi);
499         p = __get_position_from_pkg_type(ad->item->pkg_type);
500         __set_backend_mode(p);
501
502         /* Free resource */
503         free(ad->item);
504         evas_object_del(ad->notify);
505         evas_object_del(ad->win);
506         /***************/
507         /* queue_job should be called for every request that is pushed
508         into queue. In "NO" case, request is not pushed so no need of
509         calling queue_job*/
510
511         DBG("end of response_cb()\n");
512
513         drawing_popup = 0;
514
515         return;
516 }
517
518 #if 0
519 static char *__get_exe_path(const char *pkgid)
520 {
521         ail_appinfo_h handle;
522         ail_error_e ret;
523         char *str;
524         char *exe_path;
525
526         ret = ail_package_get_appinfo(pkgid, &handle);
527         if (ret != AIL_ERROR_OK) {
528                 DBGE("ail_package_get_appinfo() failed");
529                 return NULL;
530         }
531
532         ret = ail_appinfo_get_str(handle, AIL_PROP_X_SLP_EXE_PATH, &str);
533         if (ret != AIL_ERROR_OK) {
534                 DBGE("ail_appinfo_get_str() failed");
535                 ail_package_destroy_appinfo(handle);
536                 return NULL;
537         }
538
539         exe_path = strdup(str);
540         if (exe_path == NULL) {
541                 DBGE("strdup() failed");
542                 ail_package_destroy_appinfo(handle);
543                 return NULL;
544         }
545
546         ret = ail_package_destroy_appinfo(handle);
547         if (ret != AIL_ERROR_OK) {
548                 DBGE("ail_package_destroy_appinfo() failed");
549                 free(exe_path);
550                 return NULL;
551         }
552
553         return exe_path;
554 }
555 #endif
556
557 static int __X_rotate_disable_focus(Display *dpy, Window win)
558 {
559         XWMHints *hints;
560
561         hints = XAllocWMHints();
562         if (!hints) return -1;
563
564         hints->flags = InputHint | StateHint;
565         hints->input = 0;
566         hints->initial_state = NormalState;
567
568         XSetWMHints(dpy, win, hints);
569         XFree(hints);
570
571         return 0;
572 }
573
574 static int __X_rotate_get_window_property(Display *dpy, Window win, Atom atom,
575                                           Atom type, unsigned int *val,
576                                           unsigned int len)
577 {
578         unsigned char *prop_ret;
579         Atom type_ret;
580         unsigned long bytes_after;
581         unsigned long  num_ret;
582         int format_ret;
583         unsigned int i;
584         int num;
585
586         prop_ret = NULL;
587         if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
588                                type, &type_ret, &format_ret, &num_ret,
589                                &bytes_after, &prop_ret) != Success)
590                 return -1;
591
592         if (type_ret != type || format_ret != 32)
593                 num = -1;
594         else if (num_ret == 0 || !prop_ret)
595                 num = 0;
596         else {
597                 if (num_ret < len)
598                         len = num_ret;
599                 for (i = 0; i < len; i++) {
600                         val[i] = ((unsigned long *)prop_ret)[i];
601                 }
602                 num = len;
603         }
604
605         if (prop_ret)
606                 XFree(prop_ret);
607
608         return num;
609 }
610
611 static int __X_rotate_get_rotation(Display *dpy)
612 {
613         Window active_win;
614         Window root_win;
615         int rotation = -1;
616         int ret;
617
618
619         Atom atom_active_win;
620         Atom atom_win_rotate_angle;
621
622         root_win = XDefaultRootWindow(dpy);
623
624         atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
625         ret = __X_rotate_get_window_property(dpy, root_win, atom_active_win,
626                                              XA_WINDOW,
627                                              (unsigned int *)&active_win, 1);
628         if (ret < 0)
629                 return ret;
630
631         atom_win_rotate_angle =
632                 XInternAtom(dpy, "_E_ILLUME_ROTATE_ROOT_ANGLE", False);
633         ret = __X_rotate_get_window_property(dpy, root_win,
634                                           atom_win_rotate_angle, XA_CARDINAL,
635                                           (unsigned int *)&rotation, 1);
636
637         if (ret != -1)
638                 return rotation;
639
640         return -1;
641 }
642
643 static int __X_rotate_do_rotation(Window win)
644 {
645         Display *d;
646         int rotation;
647
648         d = XOpenDisplay(NULL);
649
650         rotation = __X_rotate_get_rotation(d);
651
652         if (rotation == -1) {
653                 rotation = 0;
654         }
655
656         if (rotation >= 0)
657                 elm_win_rotation_with_resize_set(win, rotation);
658
659         XCloseDisplay(d);
660
661         return 0;
662 }
663
664 static Eina_Bool __X_rotate_cb(void *data, int type, void *event)
665 {
666         Window win = (Window)data;
667         Ecore_X_Event_Client_Message *ev = event;
668
669         if (!event)
670                 return ECORE_CALLBACK_RENEW;
671
672         if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE)
673                 __X_rotate_do_rotation(win);
674
675         return ECORE_CALLBACK_RENEW;
676 }
677
678 static
679 int create_popup(struct appdata *ad)
680 {
681         DBG("start of create_popup()\n");
682
683         drawing_popup = 1;
684
685         char sentence[MAX_PKG_ARGS_LEN] = { '\0' };
686         char *pkgid = NULL;
687         char app_name[MAX_PKG_NAME_LEN] = { '\0' };
688
689         ad->win = elm_win_add(NULL, PACKAGE, ELM_WIN_DIALOG_BASIC);
690         if (!ad->win) {
691                 DBG("Failed to create a new window\n");
692                 drawing_popup = 0;
693                 return -1;
694         }
695
696         elm_win_alpha_set(ad->win, EINA_TRUE);
697         elm_win_title_set(ad->win, "test");
698         elm_win_borderless_set(ad->win, EINA_TRUE);
699         elm_win_raise(ad->win);
700
701         int rotation = 0;
702         int w;
703         int h;
704         int x;
705         int y;
706         unsigned char *prop_data = NULL;
707         int count;
708         ecore_x_window_geometry_get(ecore_x_window_root_get(
709                                             ecore_x_window_focus_get()),
710                                     &x, &y, &w, &h);
711         int ret =
712             ecore_x_window_prop_property_get(ecore_x_window_root_get
713                                      (ecore_x_window_focus_get()),
714                                      ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE,
715                                      ECORE_X_ATOM_CARDINAL,
716                                      32, &prop_data, &count);
717         if (ret && prop_data)
718                 memcpy(&rotation, prop_data, sizeof(int));
719         if (prop_data)
720                 free(prop_data);
721         evas_object_resize(ad->win, w, h);
722         evas_object_move(ad->win, x, y);
723         if (rotation != -1)
724                 elm_win_rotation_with_resize_set(ad->win, rotation);
725
726         __X_rotate_disable_focus(ecore_x_display_get(), ad->win);
727
728         ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
729                                 __X_rotate_cb, ad->win);
730
731         double s;
732         s = w / DESKTOP_W;
733         elm_config_scale_set(s);
734
735         evas_object_show(ad->win);
736
737         ad->notify = elm_popup_add(ad->win);
738         if (!ad->notify) {
739                 DBG("failed to create notify object\n");
740                 evas_object_del(ad->win);
741                 drawing_popup = 0;
742                 return -1;
743         }
744
745         /* Sentence of popup */
746         pkgid = strrchr(ad->item->pkgid, '/') == NULL ?
747             ad->item->pkgid : strrchr(ad->item->pkgid, '/') + 1;
748
749         if (ad->op_type == OPERATION_INSTALL) {
750                 snprintf(sentence, sizeof(sentence) - 1, _("Install?"));
751         } else if (ad->op_type == OPERATION_UNINSTALL) {
752                 char *label = NULL;
753                 pkgmgrinfo_pkginfo_h handle;
754                 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
755                 if (ret < 0){
756                         drawing_popup = 0;
757                         evas_object_del(ad->notify);
758                         evas_object_del(ad->win);
759                         return -1;
760                 }
761                 ret = pkgmgrinfo_pkginfo_get_label(handle, &label);
762                 if (ret < 0){
763                         drawing_popup = 0;
764                         evas_object_del(ad->notify);
765                         evas_object_del(ad->win);
766                         return -1;
767                 }
768
769                 snprintf(app_name, sizeof(app_name) - 1, label);
770                 ret = pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
771                 if (ret < 0){
772                         drawing_popup = 0;
773                         evas_object_del(ad->notify);
774                         evas_object_del(ad->win);
775                         return -1;
776                 }
777
778                 pkgid = app_name;
779
780                 snprintf(sentence, sizeof(sentence) - 1, _("Uninstall?"));
781         } else if (ad->op_type == OPERATION_REINSTALL) {
782                 snprintf(sentence, sizeof(sentence) - 1, _("Reinstall?"));
783         } else
784                 snprintf(sentence, sizeof(sentence) - 1, _("Invalid request"));
785
786         elm_object_part_text_set(ad->notify, "title,text", pkgid);
787         evas_object_size_hint_weight_set(ad->notify, EVAS_HINT_EXPAND,
788                                          EVAS_HINT_EXPAND);
789
790         evas_object_show(ad->notify);
791         /***********************************/
792
793         elm_object_text_set(ad->notify, sentence);
794
795         Evas_Object *button1 = NULL;
796         Evas_Object *button2 = NULL;
797
798         button1 = elm_button_add(ad->notify);
799         elm_object_text_set(button1, dgettext("sys_string", "IDS_COM_SK_YES"));
800         elm_object_part_content_set(ad->notify, "button1", button1);
801         evas_object_smart_callback_add(button1, "clicked", response_cb1, ad);
802
803         button2 = elm_button_add(ad->notify);
804         elm_object_text_set(button2, dgettext("sys_string", "IDS_COM_SK_NO"));
805         elm_object_part_content_set(ad->notify, "button2", button2);
806         evas_object_smart_callback_add(button2, "clicked", response_cb2, ad);
807
808         evas_object_show(ad->notify);
809
810         DBG("end of create_popup()\n");
811         return 0;
812 }
813
814 gboolean send_fail_signal(void *data)
815 {
816         DBG("send_fail_signal start\n");
817         gboolean ret_parse;
818         gint argcp;
819         gchar **argvp;
820         GError *gerr = NULL;
821         pkgmgr_installer *pi;
822         pi = pkgmgr_installer_new();
823         if (!pi) {
824                 DBG("Failure in creating the pkgmgr_installer object");
825                 return FALSE;
826         }
827         ret_parse = g_shell_parse_argv(args,
828                                        &argcp, &argvp, &gerr);
829         if (FALSE == ret_parse) {
830                 DBG("Failed to split args: %s", args);
831                 DBG("messsage: %s", gerr->message);
832                 pkgmgr_installer_free(pi);
833                 return FALSE;
834         }
835
836         pkgmgr_installer_receive_request(pi, argcp, argvp);
837         pkgmgr_installer_send_signal(pi, ptype, pname, "end", "fail");
838         pkgmgr_installer_free(pi);
839         return FALSE;
840 }
841
842 static void sighandler(int signo)
843 {
844         int status;
845         pid_t cpid;
846         int i = 0;
847         backend_info *ptr = NULL;
848         ptr = begin;
849
850         while ((cpid = waitpid(-1, &status, WNOHANG)) > 0) {
851                 DBG("child exit [%d]\n", cpid);
852                 if (WIFEXITED(status)) {
853                         DBG("child NORMAL exit [%d]\n", cpid);
854                         for(i = 0; i < num_of_backends; i++)
855                         {
856                                 if (cpid == (ptr + i)->pid) {
857                                         __set_backend_free(i);
858                                         __set_backend_mode(i);
859                                         break;
860                                 }
861                         }
862                 }
863                 else if (WIFSIGNALED(status)) {
864                         DBG("child SIGNALED exit [%d]\n", cpid);
865                         /*get the pkgid and pkgtype to send fail signal*/
866                         for(i = 0; i < num_of_backends; i++)
867                         {
868                                 if (cpid == (ptr + i)->pid) {
869                                         __set_backend_free(i);
870                                         __set_backend_mode(i);
871                                         strncpy(pname, (ptr + i)->pkgid, MAX_PKG_NAME_LEN-1);
872                                         strncpy(ptype, (ptr + i)->pkgtype, MAX_PKG_TYPE_LEN-1);
873                                         strncpy(args, (ptr + i)->args, MAX_PKG_ARGS_LEN-1);
874                                         g_idle_add(send_fail_signal, NULL);
875                                         break;
876                                 }
877                         }
878                 }
879         }
880
881 }
882
883 void req_cb(void *cb_data, const char *req_id, const int req_type,
884             const char *pkg_type, const char *pkgid, const char *args,
885             const char *cookie, int *ret)
886 {
887         static int sig_reg = 0;
888         int err = -1;
889         int p = 0;
890
891         DBG(">> in callback >> Got request: [%s] [%d] [%s] [%s] [%s] [%s]",
892             req_id, req_type, pkg_type, pkgid, args, cookie);
893
894         struct appdata *ad = (struct appdata *)cb_data;
895
896         pm_dbus_msg *item = calloc(1, sizeof(pm_dbus_msg));
897         memset(item, 0x00, sizeof(pm_dbus_msg));
898
899         strncpy(item->req_id, req_id, sizeof(item->req_id) - 1);
900         item->req_type = req_type;
901         strncpy(item->pkg_type, pkg_type, sizeof(item->pkg_type) - 1);
902         strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
903         strncpy(item->args, args, sizeof(item->args) - 1);
904         strncpy(item->cookie, cookie, sizeof(item->cookie) - 1);
905
906         if (sig_reg == 0) {
907                 struct sigaction act;
908
909                 act.sa_handler = sighandler;
910                 sigemptyset(&act.sa_mask);
911                 act.sa_flags = SA_NOCLDSTOP;
912
913                 if (sigaction(SIGCHLD, &act, NULL) < 0) {
914                         DBG("signal: SIGCHLD failed\n");
915                 } else
916                         DBG("signal: SIGCHLD succeed\n");
917                 if (g_timeout_add_seconds(2, exit_server, NULL))
918                         DBG("g_timeout_add_seconds() Added to Main Loop");
919
920                 sig_reg = 1;
921         }
922
923         DBG("req_type=(%d) drawing_popup=(%d) backend_flag=(%d)\n", req_type,
924             drawing_popup, backend_flag);
925
926         char *quiet = NULL;
927
928         switch (item->req_type) {
929         case COMM_REQ_TO_INSTALLER:
930                 /* -q option should be located at the end of command !! */
931                 if (((quiet = strstr(args, " -q")) &&
932                      (quiet[strlen(quiet)] == '\0')) ||
933                     ((quiet = strstr(args, " '-q'")) &&
934                      (quiet[strlen(quiet)] == '\0'))) {
935                         /* quiet mode */
936                         err = _pm_queue_push(item);
937                         p = __get_position_from_pkg_type(item->pkg_type);
938                         __set_backend_mode(p);
939                         /* Free resource */
940                         free(item);
941                         if (err == 0)
942                                 g_idle_add(queue_job, NULL);
943                         *ret = COMM_RET_OK;
944                 } else {
945                         /* non quiet mode */
946                         p = __get_position_from_pkg_type(item->pkg_type);
947                         if (drawing_popup == 0 &&
948                                 !__is_backend_busy(p) &&
949                                 __check_backend_mode()) {
950                                 /* if there is no popup */
951                                 ad->item = item;
952
953                                 if (strstr(args, " -i ")
954                                     || strstr(args, " '-i' "))
955                                         ad->op_type = OPERATION_INSTALL;
956                                 else if (strstr(args, " -d ")
957                                          || strstr(args, " '-d' ")) {
958                                         ad->op_type = OPERATION_UNINSTALL;
959
960                                         /* 2011-04-01 
961                    Change the mode temporarily. This should be removed */
962                                         /*strncat(item->args, " -q",
963                                                 strlen(" -q"));*/
964                                 } else if (strstr(args, " -r ")
965                                         || strstr(args, " '-r' "))
966                                         ad->op_type = OPERATION_REINSTALL;
967                                 else
968                                         ad->op_type = OPERATION_MAX;
969
970                                 err = create_popup(ad);
971                                 if (err != 0) {
972                                         *ret = COMM_RET_ERROR;
973                                         DBG("create popup failed\n");
974                                         /*queue_job(NULL);*/
975                                         goto err;
976                                 } else {
977                                         *ret = COMM_RET_OK;
978                                 }
979                         } else {
980                                         DBG("info drawing_popup:%d, __is_backend_busy(p):%d, __check_backend_mode():%d\n",
981                                         drawing_popup, __is_backend_busy(p), __check_backend_mode());
982                                 /* if popup is already being drawn */
983                                 *ret = COMM_RET_ERROR;
984                                 goto err;
985                         }
986                 }
987                 break;
988         case COMM_REQ_TO_ACTIVATOR:
989                 /* In case of activate, there is no popup */
990                 err = _pm_queue_push(item);
991                 p = __get_position_from_pkg_type(item->pkg_type);
992                 __set_backend_mode(p);
993                 /* Free resource */
994                 free(item);
995
996 /*              g_idle_add(queue_job, NULL); */
997                 if (err == 0)
998                         queue_job(NULL);
999                 *ret = COMM_RET_OK;
1000                 break;
1001         case COMM_REQ_TO_CLEARER:
1002                 /* In case of clearer, there is no popup */
1003                 err = _pm_queue_push(item);
1004                 p = __get_position_from_pkg_type(item->pkg_type);
1005                 /*the backend shows the success/failure popup
1006                 so this request is non quiet*/
1007                 __unset_backend_mode(p);
1008                 /* Free resource */
1009                 free(item);
1010
1011 /*              g_idle_add(queue_job, NULL); */
1012                 if (err == 0)
1013                         queue_job(NULL);
1014                 *ret = COMM_RET_OK;
1015                 break;
1016         case COMM_REQ_TO_MOVER:
1017                 /* In case of mover, there is no popup */
1018                 err = _pm_queue_push(item);
1019                 p = __get_position_from_pkg_type(item->pkg_type);
1020                 /*the backend shows the success/failure popup
1021                 so this request is non quiet*/
1022                 __unset_backend_mode(p);
1023                 /* Free resource */
1024                 free(item);
1025                 if (err == 0)
1026                         queue_job(NULL);
1027                 *ret = COMM_RET_OK;
1028                 break;
1029         case COMM_REQ_CANCEL:
1030                 ad->item = item;
1031                 _pm_queue_delete(ad->item);
1032                 p = __get_position_from_pkg_type(item->pkg_type);
1033                 __unset_backend_mode(p);
1034                 free(item);
1035                 *ret = COMM_RET_OK;
1036                 break;
1037         default:
1038                 DBG("Check your request..\n");
1039                 *ret = COMM_RET_ERROR;
1040                 break;
1041         }
1042 err:
1043         if (*ret == COMM_RET_ERROR) {
1044                 DBG("Failed to handle request %s %s\n",item->pkg_type, item->pkgid);
1045                 pkgmgr_installer *pi;
1046                 gboolean ret_parse;
1047                 gint argcp;
1048                 gchar **argvp;
1049                 GError *gerr = NULL;
1050
1051                 pi = pkgmgr_installer_new();
1052                 if (!pi) {
1053                         DBG("Failure in creating the pkgmgr_installer object");
1054                         free(item);
1055                         return;
1056                 }
1057
1058                 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
1059                 if (FALSE == ret_parse) {
1060                         DBG("Failed to split args: %s", args);
1061                         DBG("messsage: %s", gerr->message);
1062                         pkgmgr_installer_free(pi);
1063                         free(item);
1064                         return;
1065                 }
1066
1067                 pkgmgr_installer_receive_request(pi, argcp, argvp);
1068
1069                 pkgmgr_installer_send_signal(pi, item->pkg_type,
1070                                              item->pkgid, "end",
1071                                              "fail");
1072
1073                 pkgmgr_installer_free(pi);
1074
1075                 free(item);
1076         }
1077         return;
1078 }
1079
1080 static int __check_backend_mode()
1081 {
1082         int i = 0;
1083         for(i = 0; i < num_of_backends; i++)
1084         {
1085                 if (__is_backend_mode_quiet(i))
1086                         continue;
1087                 else
1088                         return 0;
1089         }
1090         return 1;
1091 }
1092 static int __check_backend_status_for_exit()
1093 {
1094         int i = 0;
1095         for(i = 0; i < num_of_backends; i++)
1096         {
1097                 if (!__is_backend_busy(i))
1098                         continue;
1099                 else
1100                         return 0;
1101         }
1102         return 1;
1103 }
1104
1105 static int __check_queue_status_for_exit()
1106 {
1107         pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
1108         queue_info_map *ptr = NULL;
1109         ptr = start;
1110         int i = 0;
1111         int c = 0;
1112         int slot = -1;
1113         for(i = 0; i < entries; i++)
1114         {
1115                 if (ptr->queue_slot <= slot) {
1116                         ptr++;
1117                         continue;
1118                 }
1119                 else {
1120                         head[c] = ptr->head;
1121                         slot = ptr->queue_slot;
1122                         c++;
1123                         ptr++;
1124                 }
1125         }
1126         for(i = 0; i < num_of_backends; i++)
1127         {
1128                 if (!head[i])
1129                         continue;
1130                 else
1131                         return 0;
1132         }
1133         return 1;
1134 }
1135 gboolean exit_server(void *data)
1136 {
1137         DBG("exit_server Start\n");
1138         if (__check_backend_status_for_exit() &&
1139                 __check_queue_status_for_exit() &&
1140                         drawing_popup == 0) {
1141                         if (!getenv("PMS_STANDALONE") && ail_db_update) {
1142                                 ecore_main_loop_quit();
1143                                 return FALSE;
1144                         }
1145         }
1146         return TRUE;
1147 }
1148
1149
1150 int __app_func(const pkgmgrinfo_appinfo_h handle, void *user_data)
1151 {
1152         int ret = 0;
1153         char *appid = NULL;
1154         int *data = (int *)user_data;
1155
1156         ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
1157         if (ret != PMINFO_R_OK) {
1158                 perror("fail to activate/deactivte package");
1159                 exit(1);
1160         }
1161
1162         ret = pkgmgrinfo_appinfo_set_state_enabled(appid, (*data));
1163         if (ret != PMINFO_R_OK) {
1164                 perror("fail to activate/deactivte package");
1165                 exit(1);
1166         }
1167
1168         ret = ail_desktop_appinfo_modify_bool(appid,
1169                                 AIL_PROP_X_SLP_ENABLED_BOOL,
1170                                 (*data), TRUE);
1171         if (ret != AIL_ERROR_OK) {
1172                 perror("fail to activate/deactivte package");
1173                 exit(1);
1174         }
1175         return 0;
1176 }
1177
1178
1179 gboolean queue_job(void *data)
1180 {
1181         /* DBG("queue_job start"); */
1182         pm_dbus_msg *item;
1183         backend_info *ptr = NULL;
1184         ptr = begin;
1185         int x = 0;
1186         /* Pop a job from queue */
1187 pop:
1188         if (!__is_backend_busy(pos % num_of_backends)) {
1189                 item = _pm_queue_pop(pos % num_of_backends);
1190                 pos = (pos + 1) % num_of_backends;
1191         }
1192         else {
1193                 pos = (pos + 1) % num_of_backends;
1194                 goto pop;
1195         }
1196
1197         int ret = 0;
1198         char *backend_cmd = NULL;
1199
1200         /* queue is empty and backend process is not running */
1201         if ( (item == NULL) || (item->req_type == -1) ) {
1202                 if(item)
1203                         free(item);
1204                 goto pop;
1205         }
1206         __set_backend_busy((pos + num_of_backends - 1) % num_of_backends);
1207
1208         switch (item->req_type) {
1209         case COMM_REQ_TO_INSTALLER:
1210                 DBG("installer start");
1211                 _save_queue_status(item, "processing");
1212                 DBG("saved queue status. Now try fork()");
1213                 /*save pkg type and pkg name for future*/
1214                 x = (pos + num_of_backends - 1) % num_of_backends;
1215                 strncpy((ptr + x)->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
1216                 strncpy((ptr + x)->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
1217                 strncpy((ptr + x)->args, item->args, MAX_PKG_ARGS_LEN-1);
1218                 (ptr + x)->pid = fork();
1219                 DBG("child forked [%d]\n", (ptr + x)->pid);
1220
1221                 switch ((ptr + x)->pid) {
1222                 case 0: /* child */
1223                         DBG("before run _get_backend_cmd()");
1224                         /*Check for efl-tpk app*/
1225                         backend_cmd = _get_backend_cmd(item->pkg_type);
1226
1227                         if (strcmp(item->pkg_type, "tpk") == 0) {
1228                                 ret = __is_efl_tpk_app(item->pkgid);
1229                                 if (ret == 1) {
1230                                         if (backend_cmd)
1231                                                 free(backend_cmd);
1232                                         backend_cmd = _get_backend_cmd("efltpk");
1233                                 }
1234                         }
1235
1236                         if (NULL == backend_cmd)
1237                                 break;
1238
1239                         DBG("Try to exec [%s][%s]", item->pkg_type,
1240                             backend_cmd);
1241                         fprintf(stdout, "Try to exec [%s][%s]\n",
1242                                 item->pkg_type, backend_cmd);
1243
1244                         /* Create args vector
1245                          * req_id + pkgid + args
1246                          *
1247                          * vector size = # of args +
1248                          *(req_id + pkgid + NULL termination = 3)
1249                          * Last value must be NULL for execv.
1250                          */
1251                         gboolean ret_parse;
1252                         gint argcp;
1253                         gchar **argvp;
1254                         GError *gerr = NULL;
1255                         ret_parse = g_shell_parse_argv(item->args,
1256                                                        &argcp, &argvp, &gerr);
1257                         if (FALSE == ret_parse) {
1258                                 DBG("Failed to split args: %s", item->args);
1259                                 DBG("messsage: %s", gerr->message);
1260                                 exit(1);
1261                         }
1262
1263                         /* Setup argument !!! */
1264                         /*char **args_vector =
1265                            calloc(argcp + 4, sizeof(char *)); */
1266                         char **args_vector = calloc(argcp + 1, sizeof(char *));
1267                         /*args_vector[0] = strdup(backend_cmd);
1268                            args_vector[1] = strdup(item->req_id);
1269                            args_vector[2] = strdup(item->pkgid); */
1270                         int arg_idx;
1271                         for (arg_idx = 0; arg_idx < argcp; arg_idx++) {
1272                                 /* args_vector[arg_idx+3] = argvp[arg_idx]; */
1273                                 args_vector[arg_idx] = argvp[arg_idx];
1274                         }
1275
1276                         /* dbg */
1277                         /*for(arg_idx = 0; arg_idx < argcp+3; arg_idx++) { */
1278                         for (arg_idx = 0; arg_idx < argcp + 1; arg_idx++) {
1279                                 DBG(">>>>>> args_vector[%d]=%s",
1280                                     arg_idx, args_vector[arg_idx]);
1281                         }
1282
1283                         /* Execute backend !!! */
1284                         ret = execv(backend_cmd, args_vector);
1285
1286                         /* Code below: exec failure. Should not be happened! */
1287                         DBG(">>>>>> OOPS 2!!!");
1288
1289                         /* g_strfreev(args_vector); *//* FIXME: causes error */
1290
1291                         if (ret == -1) {
1292                                 perror("fail to exec");
1293                                 exit(1);
1294                         }
1295                         _save_queue_status(item, "done");
1296                         if (NULL != backend_cmd)
1297                                 free(backend_cmd);
1298                         exit(0);        /* exit */
1299                         break;
1300
1301                 case -1:        /* error */
1302                         fprintf(stderr, "Fail to execute fork()\n");
1303                         exit(1);
1304                         break;
1305
1306                 default:        /* parent */
1307                         DBG("parent \n");
1308                         _save_queue_status(item, "done");
1309                         break;
1310                 }
1311                 break;
1312         case COMM_REQ_TO_ACTIVATOR:
1313                 DBG("activator start");
1314                 int val = 0;
1315                 _save_queue_status(item, "processing");
1316                 DBG("saved queue status. Now try fork()");
1317                 /*save pkg type and pkg name for future*/
1318                 x = (pos + num_of_backends - 1) % num_of_backends;
1319                 strncpy((ptr + x)->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
1320                 strncpy((ptr + x)->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
1321                 strncpy((ptr + x)->args, item->args, MAX_PKG_ARGS_LEN-1);
1322                 (ptr + x)->pid = fork();
1323                 DBG("child forked [%d]\n", (ptr + x)->pid);
1324
1325                 switch ((ptr + x)->pid) {
1326                 case 0: /* child */
1327                         if (item->args[0] == '1')       /* activate */
1328                                 val = 1;
1329                         else if (item->args[0] == '0')  /* deactivate */
1330                                 val = 0;
1331                         else {
1332                                 DBG("error in args parameter:[%c]\n",
1333                                     item->args[0]);
1334                                 exit(1);
1335                         }
1336
1337                         DBG("activated val %d", val);
1338
1339                         gboolean ret_parse;
1340                         gint argcp;
1341                         gchar **argvp;
1342                         GError *gerr = NULL;
1343                         char *label = NULL;
1344                         ret_parse = g_shell_parse_argv(item->args,
1345                                                        &argcp, &argvp, &gerr);
1346                         if (FALSE == ret_parse) {
1347                                 DBG("Failed to split args: %s", item->args);
1348                                 DBG("messsage: %s", gerr->message);
1349                                 exit(1);
1350                         }
1351
1352                         if (!strcmp(argvp[1], "APP")) { /* in case of application */
1353                                 DBG("(De)activate APP");
1354                                 int opt;
1355                                 while ((opt = getopt(argcp, argvp, "l:")) != -1) {
1356                                         switch (opt) {
1357                                         case 'l':
1358                                                 label = strdup(optarg);
1359                                                 DBG("activated label %s", label);
1360                                                 break;
1361                                         default: /* '?' */
1362                                                 DBGE("Incorrect argument %s\n", item->args);
1363                                                 exit(1);
1364                                         }
1365                                 }
1366
1367                                 ret = pkgmgrinfo_appinfo_set_state_enabled(item->pkgid, val);
1368                                 if (ret != PMINFO_R_OK) {
1369                                         perror("fail to activate/deactivte package");
1370                                         exit(1);
1371                                 }
1372
1373                                 if (label) {
1374                                         ret = pkgmgrinfo_appinfo_set_default_label(item->pkgid, label);
1375                                         if (ret != PMINFO_R_OK) {
1376                                                 perror("fail to activate/deactivte package");
1377                                                 exit(1);
1378                                         }
1379
1380                                         ret = ail_desktop_appinfo_modify_str(item->pkgid,
1381                                                                 AIL_PROP_NAME_STR,
1382                                                                 label, FALSE);
1383                                         if (ret != AIL_ERROR_OK) {
1384                                                 perror("fail to activate/deactivte package");
1385                                                 exit(1);
1386                                         }
1387                                         free(label);
1388                                 }
1389
1390                                 ret = ail_desktop_appinfo_modify_bool(item->pkgid,
1391                                                         AIL_PROP_X_SLP_ENABLED_BOOL,
1392                                                         val, TRUE);
1393                                 if (ret != AIL_ERROR_OK) {
1394                                         perror("fail to activate/deactivte package");
1395                                         exit(1);
1396                                 }
1397                         } else { /* in case of package */
1398                                 DBG("(De)activate PKG");
1399                                 pkgmgrinfo_pkginfo_h handle;
1400                                 ret = pkgmgrinfo_pkginfo_get_pkginfo(item->pkgid, &handle);
1401                                 if (ret != PMINFO_R_OK)
1402                                         exit(1);
1403                                 ret = pkgmgrinfo_appinfo_get_list(handle, PMINFO_ALL_APP, __app_func, &val);
1404                                 if (ret != PMINFO_R_OK) {
1405                                         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1406                                         exit(1);
1407                                 }
1408                                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1409                         }
1410
1411                         _save_queue_status(item, "done");
1412                         exit(0);
1413                         break;
1414
1415                 case -1:        /* error */
1416                         fprintf(stderr, "Fail to execute fork()\n");
1417                         exit(1);
1418                         break;
1419
1420                 default:        /* parent */
1421                         DBG("parent exit\n");
1422                         _save_queue_status(item, "done");
1423                         break;
1424                 }
1425                 break;
1426         case COMM_REQ_TO_MOVER:
1427         case COMM_REQ_TO_CLEARER:
1428                 DBG("cleaner start");
1429                 _save_queue_status(item, "processing");
1430                 DBG("saved queue status. Now try fork()");
1431                 /*save pkg type and pkg name for future*/
1432                 x = (pos + num_of_backends - 1) % num_of_backends;
1433                 strncpy((ptr + x)->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
1434                 strncpy((ptr + x)->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
1435                 strncpy((ptr + x)->args, item->args, MAX_PKG_ARGS_LEN-1);
1436                 (ptr + x)->pid = fork();
1437                 DBG("child forked [%d]\n", (ptr + x)->pid);
1438
1439                 switch ((ptr + x)->pid) {
1440                 case 0: /* child */
1441                         DBG("before run _get_backend_cmd()");
1442                         backend_cmd = _get_backend_cmd(item->pkg_type);
1443                         if (NULL == backend_cmd)
1444                                 break;
1445
1446                         DBG("Try to exec [%s][%s]", item->pkg_type,
1447                             backend_cmd);
1448                         fprintf(stdout, "Try to exec [%s][%s]\n",
1449                                 item->pkg_type, backend_cmd);
1450
1451                         /* Create args vector
1452                          * req_id + pkgid + args
1453                          *
1454                          * vector size = # of args +
1455                          *(req_id + pkgid + NULL termination = 3)
1456                          * Last value must be NULL for execv.
1457                          */
1458                         gboolean ret_parse;
1459                         gint argcp;
1460                         gchar **argvp;
1461                         GError *gerr = NULL;
1462                         ret_parse = g_shell_parse_argv(item->args,
1463                                                        &argcp, &argvp, &gerr);
1464                         if (FALSE == ret_parse) {
1465                                 DBG("Failed to split args: %s", item->args);
1466                                 DBG("messsage: %s", gerr->message);
1467                                 exit(1);
1468                         }
1469
1470                         /* Setup argument !!! */
1471                         /*char **args_vector =
1472                            calloc(argcp + 4, sizeof(char *)); */
1473                         char **args_vector = calloc(argcp + 1, sizeof(char *));
1474                         /*args_vector[0] = strdup(backend_cmd);
1475                            args_vector[1] = strdup(item->req_id);
1476                            args_vector[2] = strdup(item->pkgid); */
1477                         int arg_idx;
1478                         for (arg_idx = 0; arg_idx < argcp; arg_idx++) {
1479                                 /* args_vector[arg_idx+3] = argvp[arg_idx]; */
1480                                 args_vector[arg_idx] = argvp[arg_idx];
1481                         }
1482
1483                         /* dbg */
1484                         /*for(arg_idx = 0; arg_idx < argcp+3; arg_idx++) { */
1485                         for (arg_idx = 0; arg_idx < argcp + 1; arg_idx++) {
1486                                 DBG(">>>>>> args_vector[%d]=%s",
1487                                     arg_idx, args_vector[arg_idx]);
1488                         }
1489
1490                         /* Execute backend !!! */
1491                         ret = execv(backend_cmd, args_vector);
1492
1493                         /* Code below: exec failure. Should not be happened! */
1494                         DBG(">>>>>> OOPS 2!!!");
1495
1496                         /* g_strfreev(args_vector); *//* FIXME: causes error */
1497
1498                         if (ret == -1) {
1499                                 perror("fail to exec");
1500                                 exit(1);
1501                         }
1502                         _save_queue_status(item, "done");
1503                         if (NULL != backend_cmd)
1504                                 free(backend_cmd);
1505                         exit(0);
1506                         break;
1507
1508                 case -1:        /* error */
1509                         fprintf(stderr, "Fail to execute fork()\n");
1510                         exit(1);
1511                         break;
1512
1513                 default:        /* parent */
1514                         DBG("parent \n");
1515                         _save_queue_status(item, "done");
1516                         break;
1517                 }
1518                 break;
1519         default:
1520                 break;
1521         }
1522
1523         free(item);
1524
1525         return FALSE;
1526 }
1527
1528 #define IS_WHITESPACE(CHAR) \
1529 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1530
1531 void _app_str_trim(char *input)
1532 {
1533         char *trim_str = input;
1534
1535         if (input == NULL)
1536                 return;
1537
1538         while (*input != 0) {
1539                 if (!IS_WHITESPACE(*input)) {
1540                         *trim_str = *input;
1541                         trim_str++;
1542                 }
1543                 input++;
1544         }
1545
1546         *trim_str = 0;
1547         return;
1548 }
1549
1550 char *_get_backend_cmd(char *type)
1551 {
1552         FILE *fp = NULL;
1553         char buffer[1024] = { 0 };
1554         char *command = NULL;
1555         int size = 0;
1556         fp = fopen(PKG_CONF_PATH, "r");
1557         if (fp == NULL) {
1558                 return NULL;
1559         }
1560
1561         char *path = NULL;
1562         while (fgets(buffer, 1024, fp) != NULL) {
1563                 if (buffer[0] == '#')
1564                         continue;
1565
1566                 _app_str_trim(buffer);
1567
1568                 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1569                         DBG("buffer [%s]", buffer);
1570                         path = path + strlen(PKG_BACKEND);
1571                         DBG("path [%s]", path);
1572
1573                         command =
1574                             (char *)malloc(sizeof(char) * strlen(path) +
1575                                            strlen(type) + 1);
1576                         if (command == NULL) {
1577                                 fclose(fp);
1578                                 return NULL;
1579                         }
1580
1581                         size = strlen(path) + strlen(type) + 1;
1582                         snprintf(command, size, "%s%s", path, type);
1583                         command[strlen(path) + strlen(type)] = '\0';
1584                         DBG("command [%s]", command);
1585
1586                         if (fp != NULL)
1587                                 fclose(fp);
1588
1589                         return command;
1590                 }
1591
1592                 memset(buffer, 0x00, 1024);
1593         }
1594
1595         if (fp != NULL)
1596                 fclose(fp);
1597
1598         return NULL;            /* cannot find proper command */
1599 }
1600
1601 void _pm_desktop_file_monitor_init()
1602 {
1603         int wd = 0;
1604         int i = 0;
1605         int ret = 0;
1606
1607         desktop_notifier.ifd = inotify_init();
1608         if (desktop_notifier.ifd == -1) {
1609                 DBG("inotify_init error: %s\n", strerror(errno));
1610                 return;
1611         }
1612
1613         ret = _pm_desktop_file_dir_search(paths, DESKTOP_FILE_DIRS_NUM);
1614         if (ret) {
1615                 DBG("desktop file dir search failed\n");
1616                 return;
1617         }
1618
1619         for (i = 0; i < DESKTOP_FILE_DIRS_NUM && paths[i].path; i++) {
1620                 DBG("Configuration file for desktop file monitoring [%s] is added\n", paths[i].path);
1621                 if (access(paths[i].path, R_OK) != 0) {
1622                         ecore_file_mkpath(paths[i].path);
1623                         if (chmod(paths[i].path, 0777) == -1) {
1624                                 DBG("cannot chmod %s\n", paths[i].path);
1625                         }
1626                 }
1627
1628                 wd = inotify_add_watch(desktop_notifier.ifd, paths[i].path,
1629                                        IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE);
1630                 if (wd == -1) {
1631                         DBG("inotify_add_watch error: %s\n", strerror(errno));
1632                         close(desktop_notifier.ifd);
1633                         return;
1634                 }
1635
1636                 paths[i].wd = wd;
1637         }
1638
1639         desktop_notifier.handler =
1640             ecore_main_fd_handler_add(desktop_notifier.ifd, ECORE_FD_READ,
1641                                       __directory_notify, NULL, NULL, NULL);
1642         if (!desktop_notifier.handler) {
1643                 /* TODO: Handle me.. EXCEPTION!! */
1644                 DBG("cannot add handler for inotify\n");
1645         }
1646 }
1647
1648 void _pm_desktop_file_monitor_fini()
1649 {
1650         register int i;
1651
1652         if (desktop_notifier.handler) {
1653                 ecore_main_fd_handler_del(desktop_notifier.handler);
1654                 desktop_notifier.handler = NULL;
1655         }
1656
1657         for (i = 0; i < DESKTOP_FILE_DIRS_NUM; i++) {
1658                 if (paths[i].wd) {
1659                         if (inotify_rm_watch(desktop_notifier.ifd, paths[i].wd)
1660                             < 0) {
1661                                 DBG("inotify remove watch failed\n");
1662                         }
1663                         paths[i].wd = 0;
1664                 }
1665         }
1666
1667         if (desktop_notifier.ifd) {
1668                 close(desktop_notifier.ifd);
1669                 desktop_notifier.ifd = -1;
1670         }
1671 }
1672
1673
1674 int _pm_desktop_file_dir_search(pm_inotify_paths *paths, int number)
1675 {
1676         char *buf = NULL;
1677         char *noti_dir = NULL;
1678         char *saveptr = NULL;
1679         int len = 0;
1680         int i = 0;
1681         int fd = -1;
1682         int read_size = 0;
1683
1684         fd = open(DESKTOP_FILE_DIRS, O_RDONLY);
1685         if (fd < 0) {
1686                 DBG("Failed to open %s\n", DESKTOP_FILE_DIRS);
1687                 return -EFAULT;
1688         }
1689
1690         if (ioctl(fd, FIONREAD, &read_size) < 0) {
1691                 DBG("Failed to get a size of %s file.\n", DESKTOP_FILE_DIRS);
1692                 close(fd);
1693                 return -EFAULT;
1694         }
1695
1696         if (read_size <= 0) {
1697                 DBG("Buffer is not ready.\n");
1698                 close(fd);
1699                 return -EFAULT;
1700         }
1701
1702         buf = calloc(1, read_size+1);
1703         if (!buf) {
1704                 DBG("Failed to allocate heap.\n");
1705                 close(fd);
1706                 return -EFAULT;
1707         }
1708
1709         len = read(fd, buf, read_size);
1710         if (len < 0) {
1711                 DBG("Failed to read.\n");
1712                 close(fd);
1713                 free(buf);
1714                 return -EFAULT;
1715         }
1716
1717         buf[len] = 0;
1718
1719         noti_dir = strtok_r(buf, "\n", &saveptr);
1720         if (!noti_dir) {
1721                 DBG("Failed to strtok for %s.\n", buf);
1722                 close(fd);
1723                 free(buf);
1724                 return -EFAULT;
1725         }
1726
1727         do {
1728                 char *begin;
1729
1730                 begin = noti_dir;
1731                 while (*begin != 0) {
1732                         if (isspace(*begin))
1733                                 begin++;
1734                         else
1735                                 break;
1736                 }
1737                 if (*begin == '#' || *begin == 0) {
1738                         noti_dir = strtok_r(NULL, "\n", &saveptr);
1739                         continue;
1740                 }
1741
1742                 paths[i].path = strdup(begin);
1743                 noti_dir = strtok_r(NULL, "\n", &saveptr);
1744                 i++;
1745         } while (number > i && noti_dir);
1746
1747         paths[i].path = NULL;
1748         close(fd);
1749         free(buf);
1750
1751         return EXIT_SUCCESS;
1752 }
1753
1754 /**< Called before main loop */
1755 int app_create(void *user_data)
1756 {
1757         /* printf("called app_create\n"); */
1758         return 0;
1759 }
1760
1761 /**< Called after main loop */
1762 int app_terminate(void *user_data)
1763 {
1764         /* printf("called app_terminate\n"); */
1765         return 0;
1766 }
1767
1768 /**< Called when every window goes back */
1769 int app_pause(void *user_data)
1770 {
1771         /* printf("called app_pause\n"); */
1772         return 0;
1773 }
1774
1775 /**< Called when any window comes on top */
1776 int app_resume(void *user_data)
1777 {
1778         /* printf("called app_resume\n"); */
1779         return 0;
1780 }
1781
1782 /**< Called at the first idler*/
1783 int app_reset(bundle *b, void *user_data)
1784 {
1785         /* printf("called app_reset\n"); */
1786         return 0;
1787 }
1788
1789 int main(int argc, char *argv[])
1790 {
1791         FILE *fp_status = NULL;
1792         char buf[32] = { 0, };
1793         pid_t pid;
1794         char *backend_cmd = NULL;
1795         char *backend_name = NULL;
1796         backend_info *ptr = NULL;
1797         int r;
1798
1799         ecore_init();
1800
1801         DBG("server start");
1802
1803         if (argv[1]) {
1804                 if (strcmp(argv[1], "init") == 0) {
1805                         /* if current status is "processing", 
1806                            execute related backend with '-r' option */
1807                         if (!(fp_status = fopen(STATUS_FILE, "r")))
1808                                 return 0;       /*if file is not exist, terminated. */
1809
1810                         fgets(buf, 32, fp_status);
1811                         /* if processing <-- unintended termination */
1812                         if (strcmp(buf, "processing") == 0) {
1813                                 pid = fork();
1814
1815                                 if (pid == 0) { /* child */
1816                                         fgets(buf, 32, fp_status);
1817                                         backend_cmd = _get_backend_cmd(buf);
1818                                         if (!backend_cmd) {     /* if NULL, */
1819                                                 DBG("fail to get"
1820                                                     " backend command");
1821                                                 goto err;
1822                                         }
1823                                         backend_name =
1824                                             strrchr(backend_cmd, '/');
1825
1826                                         execl(backend_cmd, backend_name, "-r",
1827                                               NULL);
1828                                         if (backend_cmd)
1829                                                 free(backend_cmd);
1830                                         fprintf(fp_status, " ");
1831  err:
1832                                         fclose(fp_status);
1833                                         exit(13);
1834                                 } else if (pid < 0) {   /* error */
1835                                         DBG("fork fail");
1836                                         fclose(fp_status);
1837                                         return 0;
1838                                 } else {        /* parent */
1839
1840                                         DBG("parent end\n");
1841                                         fprintf(fp_status, " ");
1842                                         fclose(fp_status);
1843                                         return 0;
1844                                 }
1845                         }
1846                 }
1847         }
1848
1849         r = _pm_queue_init();
1850         if (r) {
1851                 DBG("Queue Initialization Failed\n");
1852                 return -1;
1853         }
1854
1855         /*Initialize inotify to monitor desktop file updates */
1856 /*      _pm_desktop_file_monitor_init(); */
1857
1858         /*Allocate memory for holding pid, pkgtype and pkgid*/
1859         ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
1860         if (ptr == NULL) {
1861                 DBG("Malloc Failed\n");
1862                 return -1;
1863         }
1864         memset(ptr, '\0', num_of_backends * sizeof(backend_info));
1865         begin = ptr;
1866
1867         /* init internationalization */
1868         r = appcore_set_i18n(PACKAGE, LOCALEDIR);
1869         if (r)
1870                 return -1;
1871
1872         g_type_init();
1873         mainloop = g_main_loop_new(NULL, FALSE);
1874         ecore_main_loop_glib_integrate();
1875
1876         struct appdata ad;
1877         struct appcore_ops ops;
1878         ops.create = app_create;
1879         ops.terminate = app_terminate;
1880         ops.pause = app_pause;
1881         ops.resume = app_resume;
1882         ops.reset = app_reset;
1883         ops.data = &ad;
1884
1885         DBG("Main loop is created.");
1886
1887         PkgMgrObject *pkg_mgr;
1888         pkg_mgr = g_object_new(PKG_MGR_TYPE_OBJECT, NULL);
1889         pkg_mgr_set_request_callback(pkg_mgr, req_cb, &ad);
1890         DBG("pkg_mgr object is created, and request callback is registered.");
1891
1892 /*      g_main_loop_run(mainloop); */
1893         appcore_efl_main(PACKAGE, &argc, &argv, &ops);
1894
1895         DBG("Quit main loop.");
1896 /*      _pm_desktop_file_monitor_fini(); */
1897         _pm_queue_final();
1898         /*Free backend info */
1899         if (begin) {
1900                 free(begin);
1901                 begin = NULL;
1902         }
1903
1904         DBG("package manager server terminated.");
1905
1906         return 0;
1907 }