4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
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>
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include <sys/types.h>
29 #include <sys/inotify.h>
31 #include <sys/ioctl.h>
35 #include <Elementary.h>
36 #include <appcore-efl.h>
38 #include <Ecore_File.h>
40 #include <pkgmgr-info.h>
42 #include <X11/Xatom.h>
43 #include <X11/Xutil.h>
45 #include "pkgmgr_installer.h"
46 #include "comm_pkg_mgr_server.h"
47 #include "pkgmgr-server.h"
49 #include "comm_config.h"
53 #define DBG(fmt, args...)
54 #define __SET_DBG_OUTPUT(fp)
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) \
67 #define LOG_TAG "PKGMGR_SERVER"
69 #define DBGE(fmt, arg...) LOGE(fmt,##arg)
70 #define DBG(fmt, arg...) LOGD(fmt,##arg)
74 #define PACKAGE "package-manager"
77 #if !defined(LOCALEDIR)
78 #define LOCALEDIR "/usr/share/locale"
81 #define DESKTOP_W 720.0
83 #define NO_MATCHING_FILE 11
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 */
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;
95 8 bit value to represent maximum 8 backends.
96 Each bit position corresponds to a queue slot which
97 is dynamically determined.
99 char backend_busy = 0;
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.
106 char backend_mode = 63; /*00111111*/
107 extern int num_of_backends;
110 extern queue_info_map *start;
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'};
118 GMainLoop *mainloop = NULL;
123 OPERATION_INSTALL = 0,
134 OPERATION_TYPE op_type;
137 struct pm_desktop_notifier_t {
139 Ecore_Fd_Handler *handler;
141 typedef struct pm_desktop_notifier_t pm_desktop_notifier;
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[]);
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);
167 /* To check whether a particular backend is free/busy*/
168 static int __is_backend_busy(int position)
170 return backend_busy & 1<<position;
172 /*To set a particular backend as busy*/
173 static void __set_backend_busy(int position)
175 backend_busy = backend_busy | 1<<position;
177 /*To set a particular backend as free */
178 static void __set_backend_free(int position)
180 backend_busy = backend_busy & ~(1<<position);
182 /* To check whether a particular backend is running in quiet mode*/
183 static int __is_backend_mode_quiet(int position)
185 return backend_mode & 1<<position;
187 /*To set a particular backend mode as quiet*/
188 static void __set_backend_mode(int position)
190 backend_mode = backend_mode | 1<<position;
192 /*To unset a particular backend mode */
193 static void __unset_backend_mode(int position)
195 backend_mode = backend_mode & ~(1<<position);
198 static int __get_position_from_pkg_type(char *pkgtype)
203 for(i = 0; i < entries; i++)
205 if (!strncmp(ptr->pkgtype, pkgtype, MAX_PKG_TYPE_LEN))
206 return ptr->queue_slot;
214 static int __xsystem(const char *argv[])
224 DBG("fork() failed");
227 if (execvp(argv[0], (char *const *)argv) == -1) {
228 DBG("execvp() failed");
234 err = waitpid(pid, &status, WUNTRACED | WCONTINUED);
236 DBG("waitpid failed\n");
239 } while (!WIFEXITED(status) && !WIFSIGNALED(status));
242 if (WIFEXITED(status))
243 return WEXITSTATUS(status);
248 static int __is_efl_tpk_app(char *pkgid)
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);
265 if (strcmp(type, "efltpk") == 0) {
266 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
269 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
274 if (strstr(pkgid, ".tpk") == NULL) {
278 __xsystem(delete_argv);
279 ret = mkdir("/tmp/efltpk-unzip", 0755);
281 DBG("Failed to create temporary directory to unzip tpk package\n");
284 /*In case of installation request, pkgid contains the pkgpath*/
285 ret = __xsystem(unzip_argv);
287 ret = __xsystem(unzip_opt_argv);
289 DBG("Unzip of tpk package failed. error:%d\n", ret);
290 if (ret == NO_MATCHING_FILE) /*no matching file found*/
300 __xsystem(delete_argv);
305 static Eina_Bool __directory_notify(void *data, Ecore_Fd_Handler *fd_handler)
309 ssize_t read_size = 0;
314 fd = ecore_main_fd_handler_fd_get(fd_handler);
315 DBG("ifd [%d]\n", fd);
317 if (ioctl(fd, FIONREAD, &read_size) < 0) {
318 DBG("Failed to get byte size\n");
320 return ECORE_CALLBACK_CANCEL;
323 if (read_size <= 0) {
324 DBG("Buffer is not ready!!!\n");
326 return ECORE_CALLBACK_RENEW;
329 buf = calloc(1, read_size+1);
331 DBG("Failed to allocate memory for event handling\n");
333 return ECORE_CALLBACK_RENEW;
336 len = read(fd, buf, read_size);
339 /*Stop monitoring about this invalid file descriptor */
341 return ECORE_CALLBACK_CANCEL;
347 struct inotify_event *event = (struct inotify_event*) &buf[i];
348 char *str_potksed = "potksed.";
350 char *package = NULL;
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]) {
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;
369 package = strdup(event->name);
373 cut = strstr(package, ".desktop");
376 DBG("Package : %s\n", package);
379 if (event->mask & IN_CLOSE_WRITE || event->mask & IN_MOVED_TO) {
380 ail_appinfo_h ai = NULL;
383 ret = ail_package_get_appinfo(package, &ai);
385 ail_package_destroy_appinfo(ai);
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);
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);
397 } else if (event->mask & IN_DELETE) {
398 if (ail_desktop_remove(package) < 0)
399 DBG("Failed to remove a package (%s)\n",
402 DBG("this event is not dealt with inotify\n");
407 i += sizeof(struct inotify_event) + event->len;
412 return ECORE_CALLBACK_RENEW;
416 void response_cb1(void *data, Evas_Object *notify, void *event_info)
418 struct appdata *ad = (struct appdata *)data;
421 DBG("start of response_cb()\n");
424 DBG("Uninstalling... [%s]\n", ad->item->pkgid);
426 if (strlen(ad->item->pkgid) == 0) {
427 DBG("package_name is empty\n");
430 if (strlen(ad->item->pkg_type) == 0) {
431 DBG("Fail : Uninstalling... [%s]\n",
434 evas_object_del(ad->notify);
435 evas_object_del(ad->win);
441 DBG("pkg_type = [%s]\n", ad->item->pkg_type);
443 ret = _pm_queue_push(ad->item);
444 p = __get_position_from_pkg_type(ad->item->pkg_type);
445 __unset_backend_mode(p);
449 evas_object_del(ad->notify);
450 evas_object_del(ad->win);
453 g_idle_add(queue_job, NULL);
455 DBG("end of response_cb()\n");
463 void response_cb2(void *data, Evas_Object *notify, void *event_info)
466 struct appdata *ad = (struct appdata *)data;
468 DBG("start of response_cb()\n");
471 pkgmgr_installer *pi;
477 pi = pkgmgr_installer_new();
479 DBG("Failure in creating the pkgmgr_installer object");
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);
492 pkgmgr_installer_receive_request(pi, argcp, argvp);
494 pkgmgr_installer_send_signal(pi, ad->item->pkg_type,
495 ad->item->pkgid, "end",
498 pkgmgr_installer_free(pi);
499 p = __get_position_from_pkg_type(ad->item->pkg_type);
500 __set_backend_mode(p);
504 evas_object_del(ad->notify);
505 evas_object_del(ad->win);
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
511 DBG("end of response_cb()\n");
519 static char *__get_exe_path(const char *pkgid)
521 ail_appinfo_h handle;
526 ret = ail_package_get_appinfo(pkgid, &handle);
527 if (ret != AIL_ERROR_OK) {
528 DBGE("ail_package_get_appinfo() failed");
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);
539 exe_path = strdup(str);
540 if (exe_path == NULL) {
541 DBGE("strdup() failed");
542 ail_package_destroy_appinfo(handle);
546 ret = ail_package_destroy_appinfo(handle);
547 if (ret != AIL_ERROR_OK) {
548 DBGE("ail_package_destroy_appinfo() failed");
557 static int __X_rotate_disable_focus(Display *dpy, Window win)
561 hints = XAllocWMHints();
562 if (!hints) return -1;
564 hints->flags = InputHint | StateHint;
566 hints->initial_state = NormalState;
568 XSetWMHints(dpy, win, hints);
574 static int __X_rotate_get_window_property(Display *dpy, Window win, Atom atom,
575 Atom type, unsigned int *val,
578 unsigned char *prop_ret;
580 unsigned long bytes_after;
581 unsigned long num_ret;
587 if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
588 type, &type_ret, &format_ret, &num_ret,
589 &bytes_after, &prop_ret) != Success)
592 if (type_ret != type || format_ret != 32)
594 else if (num_ret == 0 || !prop_ret)
599 for (i = 0; i < len; i++) {
600 val[i] = ((unsigned long *)prop_ret)[i];
611 static int __X_rotate_get_rotation(Display *dpy)
619 Atom atom_active_win;
620 Atom atom_win_rotate_angle;
622 root_win = XDefaultRootWindow(dpy);
624 atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
625 ret = __X_rotate_get_window_property(dpy, root_win, atom_active_win,
627 (unsigned int *)&active_win, 1);
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);
643 static int __X_rotate_do_rotation(Window win)
648 d = XOpenDisplay(NULL);
650 rotation = __X_rotate_get_rotation(d);
652 if (rotation == -1) {
657 elm_win_rotation_with_resize_set(win, rotation);
664 static Eina_Bool __X_rotate_cb(void *data, int type, void *event)
666 Window win = (Window)data;
667 Ecore_X_Event_Client_Message *ev = event;
670 return ECORE_CALLBACK_RENEW;
672 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE)
673 __X_rotate_do_rotation(win);
675 return ECORE_CALLBACK_RENEW;
679 int create_popup(struct appdata *ad)
681 DBG("start of create_popup()\n");
685 char sentence[MAX_PKG_ARGS_LEN] = { '\0' };
687 char app_name[MAX_PKG_NAME_LEN] = { '\0' };
689 ad->win = elm_win_add(NULL, PACKAGE, ELM_WIN_DIALOG_BASIC);
691 DBG("Failed to create a new window\n");
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);
706 unsigned char *prop_data = NULL;
708 ecore_x_window_geometry_get(ecore_x_window_root_get(
709 ecore_x_window_focus_get()),
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));
721 evas_object_resize(ad->win, w, h);
722 evas_object_move(ad->win, x, y);
724 elm_win_rotation_with_resize_set(ad->win, rotation);
726 __X_rotate_disable_focus(ecore_x_display_get(), ad->win);
728 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
729 __X_rotate_cb, ad->win);
733 elm_config_scale_set(s);
735 evas_object_show(ad->win);
737 ad->notify = elm_popup_add(ad->win);
739 DBG("failed to create notify object\n");
740 evas_object_del(ad->win);
745 /* Sentence of popup */
746 pkgid = strrchr(ad->item->pkgid, '/') == NULL ?
747 ad->item->pkgid : strrchr(ad->item->pkgid, '/') + 1;
749 if (ad->op_type == OPERATION_INSTALL) {
750 snprintf(sentence, sizeof(sentence) - 1, _("Install?"));
751 } else if (ad->op_type == OPERATION_UNINSTALL) {
753 pkgmgrinfo_pkginfo_h handle;
754 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
757 evas_object_del(ad->notify);
758 evas_object_del(ad->win);
761 ret = pkgmgrinfo_pkginfo_get_label(handle, &label);
764 evas_object_del(ad->notify);
765 evas_object_del(ad->win);
769 snprintf(app_name, sizeof(app_name) - 1, label);
770 ret = pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
773 evas_object_del(ad->notify);
774 evas_object_del(ad->win);
780 snprintf(sentence, sizeof(sentence) - 1, _("Uninstall?"));
781 } else if (ad->op_type == OPERATION_REINSTALL) {
782 snprintf(sentence, sizeof(sentence) - 1, _("Reinstall?"));
784 snprintf(sentence, sizeof(sentence) - 1, _("Invalid request"));
786 elm_object_part_text_set(ad->notify, "title,text", pkgid);
787 evas_object_size_hint_weight_set(ad->notify, EVAS_HINT_EXPAND,
790 evas_object_show(ad->notify);
791 /***********************************/
793 elm_object_text_set(ad->notify, sentence);
795 Evas_Object *button1 = NULL;
796 Evas_Object *button2 = NULL;
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);
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);
808 evas_object_show(ad->notify);
810 DBG("end of create_popup()\n");
814 gboolean send_fail_signal(void *data)
816 DBG("send_fail_signal start\n");
821 pkgmgr_installer *pi;
822 pi = pkgmgr_installer_new();
824 DBG("Failure in creating the pkgmgr_installer object");
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);
836 pkgmgr_installer_receive_request(pi, argcp, argvp);
837 pkgmgr_installer_send_signal(pi, ptype, pname, "end", "fail");
838 pkgmgr_installer_free(pi);
842 static void sighandler(int signo)
847 backend_info *ptr = NULL;
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++)
856 if (cpid == (ptr + i)->pid) {
857 __set_backend_free(i);
858 __set_backend_mode(i);
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++)
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);
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)
887 static int sig_reg = 0;
891 DBG(">> in callback >> Got request: [%s] [%d] [%s] [%s] [%s] [%s]",
892 req_id, req_type, pkg_type, pkgid, args, cookie);
894 struct appdata *ad = (struct appdata *)cb_data;
896 pm_dbus_msg *item = calloc(1, sizeof(pm_dbus_msg));
897 memset(item, 0x00, sizeof(pm_dbus_msg));
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);
907 struct sigaction act;
909 act.sa_handler = sighandler;
910 sigemptyset(&act.sa_mask);
911 act.sa_flags = SA_NOCLDSTOP;
913 if (sigaction(SIGCHLD, &act, NULL) < 0) {
914 DBG("signal: SIGCHLD failed\n");
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");
923 DBG("req_type=(%d) drawing_popup=(%d) backend_flag=(%d)\n", req_type,
924 drawing_popup, backend_flag);
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'))) {
936 err = _pm_queue_push(item);
937 p = __get_position_from_pkg_type(item->pkg_type);
938 __set_backend_mode(p);
942 g_idle_add(queue_job, NULL);
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 */
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;
961 Change the mode temporarily. This should be removed */
962 /*strncat(item->args, " -q",
964 } else if (strstr(args, " -r ")
965 || strstr(args, " '-r' "))
966 ad->op_type = OPERATION_REINSTALL;
968 ad->op_type = OPERATION_MAX;
970 err = create_popup(ad);
972 *ret = COMM_RET_ERROR;
973 DBG("create popup failed\n");
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;
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);
996 /* g_idle_add(queue_job, NULL); */
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);
1011 /* g_idle_add(queue_job, NULL); */
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);
1029 case COMM_REQ_CANCEL:
1031 _pm_queue_delete(ad->item);
1032 p = __get_position_from_pkg_type(item->pkg_type);
1033 __unset_backend_mode(p);
1038 DBG("Check your request..\n");
1039 *ret = COMM_RET_ERROR;
1043 if (*ret == COMM_RET_ERROR) {
1044 DBG("Failed to handle request %s %s\n",item->pkg_type, item->pkgid);
1045 pkgmgr_installer *pi;
1049 GError *gerr = NULL;
1051 pi = pkgmgr_installer_new();
1053 DBG("Failure in creating the pkgmgr_installer object");
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);
1067 pkgmgr_installer_receive_request(pi, argcp, argvp);
1069 pkgmgr_installer_send_signal(pi, item->pkg_type,
1073 pkgmgr_installer_free(pi);
1080 static int __check_backend_mode()
1083 for(i = 0; i < num_of_backends; i++)
1085 if (__is_backend_mode_quiet(i))
1092 static int __check_backend_status_for_exit()
1095 for(i = 0; i < num_of_backends; i++)
1097 if (!__is_backend_busy(i))
1105 static int __check_queue_status_for_exit()
1107 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
1108 queue_info_map *ptr = NULL;
1113 for(i = 0; i < entries; i++)
1115 if (ptr->queue_slot <= slot) {
1120 head[c] = ptr->head;
1121 slot = ptr->queue_slot;
1126 for(i = 0; i < num_of_backends; i++)
1135 gboolean exit_server(void *data)
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();
1150 int __app_func(const pkgmgrinfo_appinfo_h handle, void *user_data)
1154 int *data = (int *)user_data;
1156 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
1157 if (ret != PMINFO_R_OK) {
1158 perror("fail to activate/deactivte package");
1162 ret = pkgmgrinfo_appinfo_set_state_enabled(appid, (*data));
1163 if (ret != PMINFO_R_OK) {
1164 perror("fail to activate/deactivte package");
1168 ret = ail_desktop_appinfo_modify_bool(appid,
1169 AIL_PROP_X_SLP_ENABLED_BOOL,
1171 if (ret != AIL_ERROR_OK) {
1172 perror("fail to activate/deactivte package");
1179 gboolean queue_job(void *data)
1181 /* DBG("queue_job start"); */
1183 backend_info *ptr = NULL;
1186 /* Pop a job from queue */
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;
1193 pos = (pos + 1) % num_of_backends;
1198 char *backend_cmd = NULL;
1200 /* queue is empty and backend process is not running */
1201 if ( (item == NULL) || (item->req_type == -1) ) {
1206 __set_backend_busy((pos + num_of_backends - 1) % num_of_backends);
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);
1221 switch ((ptr + x)->pid) {
1223 DBG("before run _get_backend_cmd()");
1224 /*Check for efl-tpk app*/
1225 backend_cmd = _get_backend_cmd(item->pkg_type);
1227 if (strcmp(item->pkg_type, "tpk") == 0) {
1228 ret = __is_efl_tpk_app(item->pkgid);
1232 backend_cmd = _get_backend_cmd("efltpk");
1236 if (NULL == backend_cmd)
1239 DBG("Try to exec [%s][%s]", item->pkg_type,
1241 fprintf(stdout, "Try to exec [%s][%s]\n",
1242 item->pkg_type, backend_cmd);
1244 /* Create args vector
1245 * req_id + pkgid + args
1247 * vector size = # of args +
1248 *(req_id + pkgid + NULL termination = 3)
1249 * Last value must be NULL for execv.
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);
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); */
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];
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]);
1283 /* Execute backend !!! */
1284 ret = execv(backend_cmd, args_vector);
1286 /* Code below: exec failure. Should not be happened! */
1287 DBG(">>>>>> OOPS 2!!!");
1289 /* g_strfreev(args_vector); *//* FIXME: causes error */
1292 perror("fail to exec");
1295 _save_queue_status(item, "done");
1296 if (NULL != backend_cmd)
1301 case -1: /* error */
1302 fprintf(stderr, "Fail to execute fork()\n");
1306 default: /* parent */
1308 _save_queue_status(item, "done");
1312 case COMM_REQ_TO_ACTIVATOR:
1313 DBG("activator start");
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);
1325 switch ((ptr + x)->pid) {
1327 if (item->args[0] == '1') /* activate */
1329 else if (item->args[0] == '0') /* deactivate */
1332 DBG("error in args parameter:[%c]\n",
1337 DBG("activated val %d", val);
1342 GError *gerr = 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);
1352 if (!strcmp(argvp[1], "APP")) { /* in case of application */
1353 DBG("(De)activate APP");
1355 while ((opt = getopt(argcp, argvp, "l:")) != -1) {
1358 label = strdup(optarg);
1359 DBG("activated label %s", label);
1362 DBGE("Incorrect argument %s\n", item->args);
1367 ret = pkgmgrinfo_appinfo_set_state_enabled(item->pkgid, val);
1368 if (ret != PMINFO_R_OK) {
1369 perror("fail to activate/deactivte package");
1374 ret = pkgmgrinfo_appinfo_set_default_label(item->pkgid, label);
1375 if (ret != PMINFO_R_OK) {
1376 perror("fail to activate/deactivte package");
1380 ret = ail_desktop_appinfo_modify_str(item->pkgid,
1383 if (ret != AIL_ERROR_OK) {
1384 perror("fail to activate/deactivte package");
1390 ret = ail_desktop_appinfo_modify_bool(item->pkgid,
1391 AIL_PROP_X_SLP_ENABLED_BOOL,
1393 if (ret != AIL_ERROR_OK) {
1394 perror("fail to activate/deactivte package");
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)
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);
1408 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1411 _save_queue_status(item, "done");
1415 case -1: /* error */
1416 fprintf(stderr, "Fail to execute fork()\n");
1420 default: /* parent */
1421 DBG("parent exit\n");
1422 _save_queue_status(item, "done");
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);
1439 switch ((ptr + x)->pid) {
1441 DBG("before run _get_backend_cmd()");
1442 backend_cmd = _get_backend_cmd(item->pkg_type);
1443 if (NULL == backend_cmd)
1446 DBG("Try to exec [%s][%s]", item->pkg_type,
1448 fprintf(stdout, "Try to exec [%s][%s]\n",
1449 item->pkg_type, backend_cmd);
1451 /* Create args vector
1452 * req_id + pkgid + args
1454 * vector size = # of args +
1455 *(req_id + pkgid + NULL termination = 3)
1456 * Last value must be NULL for execv.
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);
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); */
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];
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]);
1490 /* Execute backend !!! */
1491 ret = execv(backend_cmd, args_vector);
1493 /* Code below: exec failure. Should not be happened! */
1494 DBG(">>>>>> OOPS 2!!!");
1496 /* g_strfreev(args_vector); *//* FIXME: causes error */
1499 perror("fail to exec");
1502 _save_queue_status(item, "done");
1503 if (NULL != backend_cmd)
1508 case -1: /* error */
1509 fprintf(stderr, "Fail to execute fork()\n");
1513 default: /* parent */
1515 _save_queue_status(item, "done");
1528 #define IS_WHITESPACE(CHAR) \
1529 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1531 void _app_str_trim(char *input)
1533 char *trim_str = input;
1538 while (*input != 0) {
1539 if (!IS_WHITESPACE(*input)) {
1550 char *_get_backend_cmd(char *type)
1553 char buffer[1024] = { 0 };
1554 char *command = NULL;
1556 fp = fopen(PKG_CONF_PATH, "r");
1562 while (fgets(buffer, 1024, fp) != NULL) {
1563 if (buffer[0] == '#')
1566 _app_str_trim(buffer);
1568 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1569 DBG("buffer [%s]", buffer);
1570 path = path + strlen(PKG_BACKEND);
1571 DBG("path [%s]", path);
1574 (char *)malloc(sizeof(char) * strlen(path) +
1576 if (command == NULL) {
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);
1592 memset(buffer, 0x00, 1024);
1598 return NULL; /* cannot find proper command */
1601 void _pm_desktop_file_monitor_init()
1607 desktop_notifier.ifd = inotify_init();
1608 if (desktop_notifier.ifd == -1) {
1609 DBG("inotify_init error: %s\n", strerror(errno));
1613 ret = _pm_desktop_file_dir_search(paths, DESKTOP_FILE_DIRS_NUM);
1615 DBG("desktop file dir search failed\n");
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);
1628 wd = inotify_add_watch(desktop_notifier.ifd, paths[i].path,
1629 IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE);
1631 DBG("inotify_add_watch error: %s\n", strerror(errno));
1632 close(desktop_notifier.ifd);
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");
1648 void _pm_desktop_file_monitor_fini()
1652 if (desktop_notifier.handler) {
1653 ecore_main_fd_handler_del(desktop_notifier.handler);
1654 desktop_notifier.handler = NULL;
1657 for (i = 0; i < DESKTOP_FILE_DIRS_NUM; i++) {
1659 if (inotify_rm_watch(desktop_notifier.ifd, paths[i].wd)
1661 DBG("inotify remove watch failed\n");
1667 if (desktop_notifier.ifd) {
1668 close(desktop_notifier.ifd);
1669 desktop_notifier.ifd = -1;
1674 int _pm_desktop_file_dir_search(pm_inotify_paths *paths, int number)
1677 char *noti_dir = NULL;
1678 char *saveptr = NULL;
1684 fd = open(DESKTOP_FILE_DIRS, O_RDONLY);
1686 DBG("Failed to open %s\n", DESKTOP_FILE_DIRS);
1690 if (ioctl(fd, FIONREAD, &read_size) < 0) {
1691 DBG("Failed to get a size of %s file.\n", DESKTOP_FILE_DIRS);
1696 if (read_size <= 0) {
1697 DBG("Buffer is not ready.\n");
1702 buf = calloc(1, read_size+1);
1704 DBG("Failed to allocate heap.\n");
1709 len = read(fd, buf, read_size);
1711 DBG("Failed to read.\n");
1719 noti_dir = strtok_r(buf, "\n", &saveptr);
1721 DBG("Failed to strtok for %s.\n", buf);
1731 while (*begin != 0) {
1732 if (isspace(*begin))
1737 if (*begin == '#' || *begin == 0) {
1738 noti_dir = strtok_r(NULL, "\n", &saveptr);
1742 paths[i].path = strdup(begin);
1743 noti_dir = strtok_r(NULL, "\n", &saveptr);
1745 } while (number > i && noti_dir);
1747 paths[i].path = NULL;
1751 return EXIT_SUCCESS;
1754 /**< Called before main loop */
1755 int app_create(void *user_data)
1757 /* printf("called app_create\n"); */
1761 /**< Called after main loop */
1762 int app_terminate(void *user_data)
1764 /* printf("called app_terminate\n"); */
1768 /**< Called when every window goes back */
1769 int app_pause(void *user_data)
1771 /* printf("called app_pause\n"); */
1775 /**< Called when any window comes on top */
1776 int app_resume(void *user_data)
1778 /* printf("called app_resume\n"); */
1782 /**< Called at the first idler*/
1783 int app_reset(bundle *b, void *user_data)
1785 /* printf("called app_reset\n"); */
1789 int main(int argc, char *argv[])
1791 FILE *fp_status = NULL;
1792 char buf[32] = { 0, };
1794 char *backend_cmd = NULL;
1795 char *backend_name = NULL;
1796 backend_info *ptr = NULL;
1801 DBG("server start");
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. */
1810 fgets(buf, 32, fp_status);
1811 /* if processing <-- unintended termination */
1812 if (strcmp(buf, "processing") == 0) {
1815 if (pid == 0) { /* child */
1816 fgets(buf, 32, fp_status);
1817 backend_cmd = _get_backend_cmd(buf);
1818 if (!backend_cmd) { /* if NULL, */
1820 " backend command");
1824 strrchr(backend_cmd, '/');
1826 execl(backend_cmd, backend_name, "-r",
1830 fprintf(fp_status, " ");
1834 } else if (pid < 0) { /* error */
1838 } else { /* parent */
1840 DBG("parent end\n");
1841 fprintf(fp_status, " ");
1849 r = _pm_queue_init();
1851 DBG("Queue Initialization Failed\n");
1855 /*Initialize inotify to monitor desktop file updates */
1856 /* _pm_desktop_file_monitor_init(); */
1858 /*Allocate memory for holding pid, pkgtype and pkgid*/
1859 ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
1861 DBG("Malloc Failed\n");
1864 memset(ptr, '\0', num_of_backends * sizeof(backend_info));
1867 /* init internationalization */
1868 r = appcore_set_i18n(PACKAGE, LOCALEDIR);
1873 mainloop = g_main_loop_new(NULL, FALSE);
1874 ecore_main_loop_glib_integrate();
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;
1885 DBG("Main loop is created.");
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.");
1892 /* g_main_loop_run(mainloop); */
1893 appcore_efl_main(PACKAGE, &argc, &argv, &ops);
1895 DBG("Quit main loop.");
1896 /* _pm_desktop_file_monitor_fini(); */
1898 /*Free backend info */
1904 DBG("package manager server terminated.");