diff --git a/configure.in b/configure.in index 1fb9aa5ce..1d8ca1208 100644 --- a/configure.in +++ b/configure.in @@ -103,12 +103,15 @@ AC_SUBST(PACKAGE_LIB_DIR) if test "x${prefix}" = "xNONE"; then PACKAGE_DATA_DIR="${ac_default_prefix}/share/${PACKAGE}" LOCALE_DIR="${ac_default_prefix}/share/locale" + PACKAGE_SYSCONF_DIR="${ac_default_prefix}/etc" else PACKAGE_DATA_DIR="${prefix}/share/${PACKAGE}" LOCALE_DIR="${prefix}/share/locale" + PACKAGE_SYSCONF_DIR="${sysconfdir}" fi AC_SUBST(PACKAGE_DATA_DIR) AC_SUBST(LOCALE_DIR) +AC_SUBST(PACKAGE_SYSCONF_DIR) x_dir="" x_cflags="" @@ -289,6 +292,7 @@ data/other/Makefile data/xsession/Makefile data/xsession/enlightenment.desktop data/backgrounds/Makefile +data/etc/Makefile doc/Makefile po/Makefile intl/Makefile diff --git a/data/Makefile.am b/data/Makefile.am index c9590c2a2..99cfb88b2 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,3 +1,3 @@ MAINTAINERCLEANFILES = Makefile.in -SUBDIRS = fonts images init themes other xsession input_methods backgrounds +SUBDIRS = fonts images init themes other xsession input_methods backgrounds etc diff --git a/data/etc/.cvsignore b/data/etc/.cvsignore new file mode 100644 index 000000000..9a4d3f774 --- /dev/null +++ b/data/etc/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in +*.tar.gz diff --git a/data/etc/Makefile.am b/data/etc/Makefile.am new file mode 100644 index 000000000..13108007e --- /dev/null +++ b/data/etc/Makefile.am @@ -0,0 +1,6 @@ +MAINTAINERCLEANFILES = Makefile.in +filesdir = $(sysconfdir)/enlightenment +files_DATA = \ +sysactions.conf + +EXTRA_DIST = $(files_DATA) diff --git a/data/etc/sysactions.conf b/data/etc/sysactions.conf new file mode 100644 index 000000000..72ff13fe6 --- /dev/null +++ b/data/etc/sysactions.conf @@ -0,0 +1,54 @@ +# ENLIGHTENMENT SYSTEM ACTIONS CONFIGURATION +# +# This is a system configuration for allowing or denying certain users or +# groups to be able to do certain actions that involve system restricted +# actions such as halt, reboot, suspend, hibernate etc. +# +# This file is read in order from top to bottom - the first rule to MATCH +# will be used for a user or a group, and nothing after that is read. +# +# You must put all the ACTION definitons BEFORE user and group rule matches. +# Any action definitons after a rule match has been found will be ignored. +# This allows actions to be re-defined for different user groups, so matches +# so the command for an action can change for matches to the rules later on. +# +# Any user or group NOT matched by an allow or a deny will be ALLOWED to +# perform the action by default (system administrators should be aware of +# this and implement whatever policies they see fit). Generally speaking +# a user of a workstation, desktop or laptop is intended to have such abilities +# to perform these actions, thus the default of allow. For multi-user systems +# the system administrator is considerd capable enough to restrict what they +# see they need to. +# +# A WARNING to admins: do NOT allow access for users to this system remotely +# UNLESS you fully trust them or you have locked down permissions to halt/reboot +# suspend etc. here first. You have been warned. +# +# FORMAT: +# +# action: halt /sbin/shutdown -h now +# action: reboot /sbin/shutdown -r now +# action: suspend /etc/acpi/sleep.sh force +# action: hibernate /etc/acpi/hibernate.sh force +# +# user: username allow: halt reboot suspend hibernate +# group: groupname deny: * +# group: * deny: * +# user: * allow: suspend +# user: billy allow: halt reboot +# group: staff deny: halt suspend hibernate +# +# etc. +# +# user and group name can use glob matches (* == all for example) like the +# shell. as can action names allowed or denied. + +action: halt /sbin/shutdown -h now +action: reboot /sbin/shutdown -r now +action: suspend /etc/acpi/sleep.sh force +action: hibernate /etc/acpi/hibernate.sh force + +user: root allow: * +group: operator allow: * +group: staff allow: * +user: * deny: * diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 4919441e1..5671cc52e 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -10,7 +10,8 @@ INCLUDES = -I$(top_srcdir) \ -DPACKAGE_BIN_DIR=\"@PACKAGE_BIN_DIR@\" \ -DPACKAGE_LIB_DIR=\"@PACKAGE_LIB_DIR@\" \ -DPACKAGE_DATA_DIR=\"@PACKAGE_DATA_DIR@\" \ - -DLOCALE_DIR=\"@LOCALE_DIR@\" + -DLOCALE_DIR=\"@LOCALE_DIR@\" \ + -DPACKAGE_SYSCONF_DIR=\"@PACKAGE_SYSCONF_DIR@\" bin_PROGRAMS = \ enlightenment \ @@ -19,7 +20,8 @@ enlightenment_eapp \ enlightenment_eapp_cache_gen \ enlightenment_imc \ enlightenment_start \ -enlightenment_thumb +enlightenment_thumb \ +enlightenment_sys ENLIGHTENMENTHEADERS = \ e.h \ @@ -178,8 +180,9 @@ e_int_config_wallpaper.h \ e_int_config_wallpaper_import.h \ e_int_config_wallpaper_gradient.h \ e_color_dialog.h \ -e_fdo_menu_to_order.h - +e_fdo_menu_to_order.h \ +e_sys.h + enlightenment_src = \ e_user.c \ e_manager.c \ @@ -333,6 +336,7 @@ e_int_config_wallpaper_import.c \ e_int_config_wallpaper_gradient.c \ e_color_dialog.c \ e_fdo_menu_to_order.c \ +e_sys.c \ $(ENLIGHTENMENTHEADERS) enlightenment_SOURCES = \ @@ -379,6 +383,15 @@ e_sha1.h enlightenment_thumb_LDFLAGS = @e_libs@ @dlopen_libs@ +enlightenment_sys_SOURCES = \ +e_sys_main.c + +enlightenment_sys_LDFLAGS = @e_libs@ @dlopen_libs@ + +setuid_root_mode = a=rx,u+s +install-exec-hook: + @chmod $(setuid_root_mode) $(DESTDIR)$(bindir)/enlightenment_sys$(EXEEXT) || true + installed_headersdir = $(prefix)/include/enlightenment installed_headers_DATA = $(ENLIGHTENMENTHEADERS) diff --git a/src/bin/e_actions.c b/src/bin/e_actions.c index d77202710..10c4cad3c 100644 --- a/src/bin/e_actions.c +++ b/src/bin/e_actions.c @@ -66,8 +66,6 @@ static void _e_action_free(E_Action *act); static Evas_Bool _e_actions_cb_free(Evas_Hash *hash, const char *key, void *data, void *fdata); static E_Maximize _e_actions_maximize_parse(const char *maximize); -static E_Dialog *exit_dialog = NULL; - /* to save writing this in N places - the sctions are defined here */ /***************************************************************************/ ACT_FN_GO(window_move) @@ -1364,14 +1362,16 @@ ACT_FN_GO(desk_deskshow_toggle) e_desk_deskshow(zone); } } + /***************************************************************************/ +static E_Dialog *exit_dialog = NULL; static void _e_actions_cb_exit_dialog_ok(void *data, E_Dialog *dia) { - ecore_main_loop_quit(); e_object_del(E_OBJECT(exit_dialog)); exit_dialog = NULL; + e_sys_action_do(E_SYS_EXIT, NULL); } static void @@ -1415,10 +1415,261 @@ ACT_FN_GO(exit) /***************************************************************************/ ACT_FN_GO(restart) { - restart = 1; - ecore_main_loop_quit(); + e_sys_action_do(E_SYS_RESTART, NULL); } +/***************************************************************************/ +ACT_FN_GO(exit_now) +{ + e_sys_action_do(E_SYS_EXIT_NOW, NULL); +} + +/***************************************************************************/ +static E_Dialog *logout_dialog = NULL; + +static void +_e_actions_cb_logout_dialog_ok(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(logout_dialog)); + logout_dialog = NULL; + e_sys_action_do(E_SYS_LOGOUT, NULL); +} + +static void +_e_actions_cb_logout_dialog_cancel(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(logout_dialog)); + logout_dialog = NULL; +} + +static void +_e_actions_cb_logout_dialog_delete(E_Win *win) +{ + E_Dialog *dia; + + dia = win->data; + _e_actions_cb_logout_dialog_cancel(NULL, dia); +} + +ACT_FN_GO(logout) +{ + if (logout_dialog) e_object_del(E_OBJECT(logout_dialog)); + logout_dialog = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_logout_dialog"); + if (!logout_dialog) return; + e_win_delete_callback_set(logout_dialog->win, _e_actions_cb_logout_dialog_delete); + e_dialog_title_set(logout_dialog, _("Are you sure you want to log out?")); + e_dialog_text_set(logout_dialog, + _("You are about to log out.
" + "
" + "Are you sure you want to do this?" + )); + e_dialog_icon_set(logout_dialog, "enlightenment/logout", 64); + e_dialog_button_add(logout_dialog, _("Yes"), NULL, + _e_actions_cb_logout_dialog_ok, NULL); + e_dialog_button_add(logout_dialog, _("No"), NULL, + _e_actions_cb_logout_dialog_cancel, NULL); + e_dialog_button_focus_num(logout_dialog, 1); + e_win_centered_set(logout_dialog->win, 1); + e_dialog_show(logout_dialog); +} + +/***************************************************************************/ +static E_Dialog *halt_dialog = NULL; + +static void +_e_actions_cb_halt_dialog_ok(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(halt_dialog)); + halt_dialog = NULL; + e_sys_action_do(E_SYS_HALT, NULL); +} + +static void +_e_actions_cb_halt_dialog_cancel(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(halt_dialog)); + halt_dialog = NULL; +} + +static void +_e_actions_cb_halt_dialog_delete(E_Win *win) +{ + E_Dialog *dia; + + dia = win->data; + _e_actions_cb_halt_dialog_cancel(NULL, dia); +} + +ACT_FN_GO(halt) +{ + if (halt_dialog) e_object_del(E_OBJECT(halt_dialog)); + halt_dialog = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_halt_dialog"); + if (!halt_dialog) return; + e_win_delete_callback_set(halt_dialog->win, _e_actions_cb_halt_dialog_delete); + e_dialog_title_set(halt_dialog, _("Are you sure you want to turn off?")); + e_dialog_text_set(halt_dialog, + _("You requested to turn off your Computer.
" + "
" + "Are you sure you want to shut down?" + )); + e_dialog_icon_set(halt_dialog, "enlightenment/halt", 64); + e_dialog_button_add(halt_dialog, _("Yes"), NULL, + _e_actions_cb_halt_dialog_ok, NULL); + e_dialog_button_add(halt_dialog, _("No"), NULL, + _e_actions_cb_halt_dialog_cancel, NULL); + e_dialog_button_focus_num(halt_dialog, 1); + e_win_centered_set(halt_dialog->win, 1); + e_dialog_show(halt_dialog); +} + +/***************************************************************************/ +static E_Dialog *reboot_dialog = NULL; + +static void +_e_actions_cb_reboot_dialog_ok(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(reboot_dialog)); + reboot_dialog = NULL; + e_sys_action_do(E_SYS_REBOOT, NULL); +} + +static void +_e_actions_cb_reboot_dialog_cancel(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(reboot_dialog)); + reboot_dialog = NULL; +} + +static void +_e_actions_cb_reboot_dialog_delete(E_Win *win) +{ + E_Dialog *dia; + + dia = win->data; + _e_actions_cb_reboot_dialog_cancel(NULL, dia); +} + +ACT_FN_GO(reboot) +{ + if (reboot_dialog) e_object_del(E_OBJECT(reboot_dialog)); + reboot_dialog = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_reboot_dialog"); + if (!reboot_dialog) return; + e_win_delete_callback_set(reboot_dialog->win, _e_actions_cb_reboot_dialog_delete); + e_dialog_title_set(reboot_dialog, _("Are you sure you want to reboot?")); + e_dialog_text_set(reboot_dialog, + _("You requested to reboot your Computer.
" + "
" + "Are you sure you want to restart it?" + )); + e_dialog_icon_set(reboot_dialog, "enlightenment/reboot", 64); + e_dialog_button_add(reboot_dialog, _("Yes"), NULL, + _e_actions_cb_reboot_dialog_ok, NULL); + e_dialog_button_add(reboot_dialog, _("No"), NULL, + _e_actions_cb_reboot_dialog_cancel, NULL); + e_dialog_button_focus_num(reboot_dialog, 1); + e_win_centered_set(reboot_dialog->win, 1); + e_dialog_show(reboot_dialog); +} + +/***************************************************************************/ +static E_Dialog *suspend_dialog = NULL; + +static void +_e_actions_cb_suspend_dialog_ok(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(suspend_dialog)); + suspend_dialog = NULL; + e_sys_action_do(E_SYS_SUSPEND, NULL); +} + +static void +_e_actions_cb_suspend_dialog_cancel(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(suspend_dialog)); + suspend_dialog = NULL; +} + +static void +_e_actions_cb_suspend_dialog_delete(E_Win *win) +{ + E_Dialog *dia; + + dia = win->data; + _e_actions_cb_suspend_dialog_cancel(NULL, dia); +} + +ACT_FN_GO(suspend) +{ + if (suspend_dialog) e_object_del(E_OBJECT(suspend_dialog)); + suspend_dialog = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_suspend_dialog"); + if (!suspend_dialog) return; + e_win_delete_callback_set(suspend_dialog->win, _e_actions_cb_suspend_dialog_delete); + e_dialog_title_set(suspend_dialog, _("Are you sure you want to turn off?")); + e_dialog_text_set(suspend_dialog, + _("You requested to suspend your Computer.
" + "
" + "Are you sure you want to suspend?" + )); + e_dialog_icon_set(suspend_dialog, "enlightenment/suspend", 64); + e_dialog_button_add(suspend_dialog, _("Yes"), NULL, + _e_actions_cb_suspend_dialog_ok, NULL); + e_dialog_button_add(suspend_dialog, _("No"), NULL, + _e_actions_cb_suspend_dialog_cancel, NULL); + e_dialog_button_focus_num(suspend_dialog, 1); + e_win_centered_set(suspend_dialog->win, 1); + e_dialog_show(suspend_dialog); +} + +/***************************************************************************/ +static E_Dialog *hibernate_dialog = NULL; + +static void +_e_actions_cb_hibernate_dialog_ok(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(hibernate_dialog)); + hibernate_dialog = NULL; + e_sys_action_do(E_SYS_HIBERNATE, NULL); +} + +static void +_e_actions_cb_hibernate_dialog_cancel(void *data, E_Dialog *dia) +{ + e_object_del(E_OBJECT(hibernate_dialog)); + hibernate_dialog = NULL; +} + +static void +_e_actions_cb_hibernate_dialog_delete(E_Win *win) +{ + E_Dialog *dia; + + dia = win->data; + _e_actions_cb_hibernate_dialog_cancel(NULL, dia); +} + +ACT_FN_GO(hibernate) +{ + if (hibernate_dialog) e_object_del(E_OBJECT(hibernate_dialog)); + hibernate_dialog = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_hibernate_dialog"); + if (!hibernate_dialog) return; + e_win_delete_callback_set(hibernate_dialog->win, _e_actions_cb_hibernate_dialog_delete); + e_dialog_title_set(hibernate_dialog, _("Are you sure you want to hibernate?")); + e_dialog_text_set(hibernate_dialog, + _("You requested to hibernate your Computer.
" + "
" + "Are you sure you want to suspend to disk?" + )); + e_dialog_icon_set(hibernate_dialog, "enlightenment/hibernate", 64); + e_dialog_button_add(hibernate_dialog, _("Yes"), NULL, + _e_actions_cb_hibernate_dialog_ok, NULL); + e_dialog_button_add(hibernate_dialog, _("No"), NULL, + _e_actions_cb_hibernate_dialog_cancel, NULL); + e_dialog_button_focus_num(hibernate_dialog, 1); + e_win_centered_set(hibernate_dialog->win, 1); + e_dialog_show(hibernate_dialog); +} + +/***************************************************************************/ ACT_FN_GO(pointer_resize_push) { E_Manager *man = NULL; @@ -1438,6 +1689,7 @@ ACT_FN_GO(pointer_resize_push) } } +/***************************************************************************/ ACT_FN_GO(pointer_resize_pop) { E_Manager *man = NULL; @@ -1467,6 +1719,7 @@ ACT_FN_GO(exebuf) e_exebuf_show(zone); } +/***************************************************************************/ ACT_FN_GO(desk_lock) { /* E_Zone *zone; @@ -1768,16 +2021,32 @@ e_actions_init(void) ACT_GO_MOUSE(winlist); ACT_GO_KEY(winlist); - /* restart */ ACT_GO(restart); e_register_action_predef_name(_("Enlightenment"), _("Restart"), "restart", NULL, EDIT_RESTRICT_ACTION | EDIT_RESTRICT_PARAMS, 0); - - /* exit */ ACT_GO(exit); e_register_action_predef_name(_("Enlightenment"), _("Exit"), "exit", NULL, EDIT_RESTRICT_ACTION | EDIT_RESTRICT_PARAMS, 0); + ACT_GO(logout); + e_register_action_predef_name(_("Enlightenment"), _("Log Out"), "logout", NULL, + EDIT_RESTRICT_ACTION | EDIT_RESTRICT_PARAMS, 0); + ACT_GO(exit_now); + e_register_action_predef_name(_("Enlightenment"), _("Exit Immediately"), "exit_now", NULL, + EDIT_RESTRICT_ACTION | EDIT_RESTRICT_PARAMS, 0); + ACT_GO(halt); + e_register_action_predef_name(_("System"), _("Shut Down"), "halt", NULL, + EDIT_RESTRICT_ACTION | EDIT_RESTRICT_PARAMS, 0); + ACT_GO(reboot); + e_register_action_predef_name(_("System"), _("Reboot"), "reboot", NULL, + EDIT_RESTRICT_ACTION | EDIT_RESTRICT_PARAMS, 0); + ACT_GO(suspend); + e_register_action_predef_name(_("System"), _("Suspend"), "suspend", NULL, + EDIT_RESTRICT_ACTION | EDIT_RESTRICT_PARAMS, 0); + ACT_GO(hibernate); + e_register_action_predef_name(_("System"), _("Suspend to Disk"), "hibernate", NULL, + EDIT_RESTRICT_ACTION | EDIT_RESTRICT_PARAMS, 0); + ACT_GO(pointer_resize_push); ACT_GO(pointer_resize_pop); diff --git a/src/bin/e_ilist.c b/src/bin/e_ilist.c index 48a6305b1..1deabe5a6 100644 --- a/src/bin/e_ilist.c +++ b/src/bin/e_ilist.c @@ -175,6 +175,18 @@ e_ilist_selected_get(Evas_Object *obj) return sd->selected; } +EAPI void +e_ilist_unselect(Evas_Object *obj) +{ + E_Smart_Item *si; + + API_ENTRY return; + if (!sd->items) return; + si = evas_list_nth(sd->items, sd->selected); + if (si) edje_object_signal_emit(si->base_obj, "e,state,unselected", "e"); + sd->selected = -1; +} + EAPI const char * e_ilist_selected_label_get(Evas_Object *obj) { diff --git a/src/bin/e_ilist.h b/src/bin/e_ilist.h index 415e0e838..68142c313 100644 --- a/src/bin/e_ilist.h +++ b/src/bin/e_ilist.h @@ -18,6 +18,7 @@ EAPI void e_ilist_selected_geometry_get (Evas_Object *obj, Evas_Coord *x EAPI void e_ilist_min_size_get (Evas_Object *obj, Evas_Coord *w, Evas_Coord *h); EAPI void e_ilist_selector_set (Evas_Object *obj, int selector); EAPI int e_ilist_selector_get (Evas_Object *obj); +EAPI void e_ilist_unselect (Evas_Object *obj); EAPI void e_ilist_remove_num (Evas_Object *obj, int n); EAPI void e_ilist_remove_label (Evas_Object *obj, const char *label); EAPI const char *e_ilist_nth_label_get (Evas_Object *obj, int n); diff --git a/src/bin/e_includes.h b/src/bin/e_includes.h index 653af4970..9955c124a 100644 --- a/src/bin/e_includes.h +++ b/src/bin/e_includes.h @@ -155,3 +155,5 @@ #include "e_widget_csel.h" #include "e_color_dialog.h" #include "e_fdo_menu_to_order.h" +#include "e_sys.h" + diff --git a/src/bin/e_int_menus.c b/src/bin/e_int_menus.c index 6c4cf0443..1dee2bf26 100644 --- a/src/bin/e_int_menus.c +++ b/src/bin/e_int_menus.c @@ -18,8 +18,6 @@ struct _Main_Data }; /* local subsystem functions */ -static void _e_int_menus_quit (void); -static void _e_int_menus_quit_cb (void *data); static void _e_int_menus_main_del_hook (void *obj); static void _e_int_menus_main_about (void *data, E_Menu *m, E_Menu_Item *mi); static int _e_int_menus_main_run_defer_cb (void *data); @@ -28,6 +26,10 @@ static int _e_int_menus_main_lock_defer_cb (void *data); static void _e_int_menus_main_lock (void *data, E_Menu *m, E_Menu_Item*mi); static void _e_int_menus_main_restart (void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_main_exit (void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_int_menus_main_halt (void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_int_menus_main_reboot (void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_int_menus_main_suspend (void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_int_menus_main_hibernate (void *data, E_Menu *m, E_Menu_Item *mi); static void _e_int_menus_apps_scan (E_Menu *m); static void _e_int_menus_apps_start (void *data, E_Menu *m); static void _e_int_menus_apps_del_hook (void *obj); @@ -56,8 +58,6 @@ static void _e_int_menus_augmentation_add (E_Menu *m, Evas_List *augmentation static void _e_int_menus_augmentation_del (E_Menu *m, Evas_List *augmentation); /* local subsystem globals */ -static Ecore_Job *_e_int_menus_quit_job = NULL; - static Evas_Hash *_e_int_menus_augmentation = NULL; /* externally accessible functions */ @@ -150,6 +150,43 @@ e_int_menus_main_new(void) mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); + + if (e_sys_action_possible_get(E_SYS_HALT) || + e_sys_action_possible_get(E_SYS_REBOOT) || + e_sys_action_possible_get(E_SYS_SUSPEND) || + e_sys_action_possible_get(E_SYS_HIBERNATE)) + { + if (e_sys_action_possible_get(E_SYS_HALT)) + { + mi = e_menu_item_new(m); + e_menu_item_label_set(mi, _("Shut Down your Computer")); + e_util_menu_item_edje_icon_set(mi, "enlightenment/halt"); + e_menu_item_callback_set(mi, _e_int_menus_main_halt, NULL); + } + if (e_sys_action_possible_get(E_SYS_REBOOT)) + { + mi = e_menu_item_new(m); + e_menu_item_label_set(mi, _("Reboot your Computer")); + e_util_menu_item_edje_icon_set(mi, "enlightenment/reboot"); + e_menu_item_callback_set(mi, _e_int_menus_main_reboot, NULL); + } + if (e_sys_action_possible_get(E_SYS_SUSPEND)) + { + mi = e_menu_item_new(m); + e_menu_item_label_set(mi, _("Suspend your Computer")); + e_util_menu_item_edje_icon_set(mi, "enlightenment/suspend"); + e_menu_item_callback_set(mi, _e_int_menus_main_suspend, NULL); + } + if (e_sys_action_possible_get(E_SYS_HIBERNATE)) + { + mi = e_menu_item_new(m); + e_menu_item_label_set(mi, _("Hibernate your Computer")); + e_util_menu_item_edje_icon_set(mi, "enlightenment/hibernate"); + e_menu_item_callback_set(mi, _e_int_menus_main_hibernate, NULL); + } + mi = e_menu_item_new(m); + e_menu_item_separator_set(mi, 1); + } mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Restart Enlightenment")); @@ -313,27 +350,6 @@ e_int_menus_menu_augmentation_del(const char *menu, E_Int_Menu_Augmentation *mau } /* local subsystem functions */ -static void -_e_int_menus_quit(void) -{ - if (_e_int_menus_quit_job) - { - ecore_job_del(_e_int_menus_quit_job); - _e_int_menus_quit_job = NULL; - } - _e_int_menus_quit_job = ecore_job_add(_e_int_menus_quit_cb, NULL); -} - -static void -_e_int_menus_quit_cb(void *data) -{ - E_Action *a; - - a = e_action_find("exit"); - if ((a) && (a->func.go)) a->func.go(NULL, NULL); - _e_int_menus_quit_job = NULL; -} - static void _e_int_menus_main_del_hook(void *obj) { @@ -428,7 +444,46 @@ _e_int_menus_main_restart(void *data, E_Menu *m, E_Menu_Item *mi) static void _e_int_menus_main_exit(void *data, E_Menu *m, E_Menu_Item *mi) { - if (!e_util_immortal_check()) _e_int_menus_quit(); + E_Action *a; + + a = e_action_find("exit"); + if ((a) && (a->func.go)) a->func.go(NULL, NULL); +} + +static void +_e_int_menus_main_halt(void *data, E_Menu *m, E_Menu_Item *mi) +{ + E_Action *a; + + a = e_action_find("halt"); + if ((a) && (a->func.go)) a->func.go(NULL, NULL); +} + +static void +_e_int_menus_main_reboot(void *data, E_Menu *m, E_Menu_Item *mi) +{ + E_Action *a; + + a = e_action_find("reboot"); + if ((a) && (a->func.go)) a->func.go(NULL, NULL); +} + +static void +_e_int_menus_main_suspend(void *data, E_Menu *m, E_Menu_Item *mi) +{ + E_Action *a; + + a = e_action_find("suspend"); + if ((a) && (a->func.go)) a->func.go(NULL, NULL); +} + +static void +_e_int_menus_main_hibernate(void *data, E_Menu *m, E_Menu_Item *mi) +{ + E_Action *a; + + a = e_action_find("hibernate"); + if ((a) && (a->func.go)) a->func.go(NULL, NULL); } static void diff --git a/src/bin/e_main.c b/src/bin/e_main.c index 1eec4641d..72db3aece 100644 --- a/src/bin/e_main.c +++ b/src/bin/e_main.c @@ -457,6 +457,14 @@ main(int argc, char **argv) } _e_main_shutdown_push(e_thumb_shutdown); + /* init the enlightenment sys command system */ + if (!e_sys_init()) + { + e_error_message_show(_("Enlightenment cannot initialize the System Command system.\n")); + _e_main_shutdown(-1); + } + _e_main_shutdown_push(e_sys_shutdown); + /* init the enlightenment file manager */ if (!e_fm_icon_init() || !e_fm_init() || !e_fm2_init()) diff --git a/src/bin/e_sys.c b/src/bin/e_sys.c new file mode 100644 index 000000000..cd7065e91 --- /dev/null +++ b/src/bin/e_sys.c @@ -0,0 +1,192 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "e.h" + +/* local subsystem functions */ +static int _e_sys_cb_exit(void *data, int type, void *event); + +static Ecore_Event_Handler *_e_sys_exe_exit_handler = NULL; +static int _e_sys_exe_pending = 0; +static Ecore_Exe *_e_sys_halt_check_exe = NULL; +static Ecore_Exe *_e_sys_reboot_check_exe = NULL; +static Ecore_Exe *_e_sys_suspend_check_exe = NULL; +static Ecore_Exe *_e_sys_hibernate_check_exe = NULL; +static int _e_sys_can_halt = 0; +static int _e_sys_can_reboot = 0; +static int _e_sys_can_suspend = 0; +static int _e_sys_can_hibernate = 0; + +/* externally accessible functions */ +EAPI int +e_sys_init(void) +{ + char buf[4096]; + + /* this is not optimal - but it does work cleanly */ + _e_sys_exe_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _e_sys_cb_exit, NULL); + snprintf(buf, sizeof(buf), "%s/enlightenment_sys -t halt", e_prefix_bin_get()); + _e_sys_halt_check_exe = ecore_exe_run(buf, NULL); + _e_sys_exe_pending++; + snprintf(buf, sizeof(buf), "%s/enlightenment_sys -t reboot", e_prefix_bin_get()); + _e_sys_reboot_check_exe = ecore_exe_run(buf, NULL); + _e_sys_exe_pending++; + snprintf(buf, sizeof(buf), "%s/enlightenment_sys -t suspend", e_prefix_bin_get()); + _e_sys_suspend_check_exe = ecore_exe_run(buf, NULL); + _e_sys_exe_pending++; + snprintf(buf, sizeof(buf), "%s/enlightenment_sys -t hibernate", e_prefix_bin_get()); + _e_sys_hibernate_check_exe = ecore_exe_run(buf, NULL); + _e_sys_exe_pending++; + return 1; +} + +EAPI int +e_sys_shutdown(void) +{ + if (_e_sys_exe_exit_handler) + ecore_event_handler_del(_e_sys_exe_exit_handler); + _e_sys_exe_exit_handler = NULL; + _e_sys_halt_check_exe = NULL; + _e_sys_reboot_check_exe = NULL; + _e_sys_suspend_check_exe = NULL; + _e_sys_hibernate_check_exe = NULL; + return 1; +} + +EAPI int +e_sys_action_possible_get(E_Sys_Action a) +{ + switch (a) + { + case E_SYS_EXIT: + case E_SYS_RESTART: + case E_SYS_EXIT_NOW: + return 1; + case E_SYS_LOGOUT: + return 0; + case E_SYS_HALT: + return _e_sys_can_halt; + case E_SYS_REBOOT: + return _e_sys_can_reboot; + case E_SYS_SUSPEND: + return _e_sys_can_suspend; + case E_SYS_HIBERNATE: + return _e_sys_can_hibernate; + default: + return 0; + } + return 0; +} + +EAPI int +e_sys_action_do(E_Sys_Action a, char *param) +{ + char buf[4096]; + + switch (a) + { + case E_SYS_EXIT: + if (!e_util_immortal_check()) + ecore_main_loop_quit(); + break; + case E_SYS_RESTART: + restart = 1; + ecore_main_loop_quit(); + break; + case E_SYS_EXIT_NOW: + exit(0); + break; + case E_SYS_LOGOUT: + /* FIXME: go through to every window and if it wants delete req - ask + * it to delete, otherwise just close it. set handler for window + * deletes, and once all windows are deleted - exit, OR if a timer + * expires - pop up dialog saying something is not responding + */ + break; + case E_SYS_HALT: + /* shutdown -h now */ + snprintf(buf, sizeof(buf), "%s/enlightenment_sys halt", + e_prefix_bin_get()); + ecore_exe_run(buf, NULL); + /* FIXME: track command return value and have dialog */ + break; + case E_SYS_REBOOT: + /* shutdown -r now */ + snprintf(buf, sizeof(buf), "%s/enlightenment_sys reboot", + e_prefix_bin_get()); + ecore_exe_run(buf, NULL); + /* FIXME: track command return value and have dialog */ + break; + case E_SYS_SUSPEND: + /* /etc/acpi/sleep.sh force */ + snprintf(buf, sizeof(buf), "%s/enlightenment_sys suspend", + e_prefix_bin_get()); + ecore_exe_run(buf, NULL); + /* FIXME: track command return value and have dialog */ + break; + case E_SYS_HIBERNATE: + /* /etc/acpi/hibernate.sh force */ + snprintf(buf, sizeof(buf), "%s/enlightenment_sys hibernate", + e_prefix_bin_get()); + ecore_exe_run(buf, NULL); + /* FIXME: track command return value and have dialog */ + break; + default: + return 0; + } + return 0; +} + +/* local subsystem functions */ +static int +_e_sys_cb_exit(void *data, int type, void *event) +{ + Ecore_Exe_Event_Del *ev; + + ev = event; + if ((_e_sys_halt_check_exe) && (ev->exe == _e_sys_halt_check_exe)) + { + if (ev->exit_code == 0) + { + _e_sys_can_halt = 1; + _e_sys_halt_check_exe = NULL; + } + _e_sys_exe_pending--; + } + else if ((_e_sys_reboot_check_exe) && (ev->exe == _e_sys_reboot_check_exe)) + { + if (ev->exit_code == 0) + { + _e_sys_can_reboot = 1; + _e_sys_reboot_check_exe = NULL; + } + _e_sys_exe_pending--; + } + else if ((_e_sys_suspend_check_exe) && (ev->exe == _e_sys_suspend_check_exe)) + { + if (ev->exit_code == 0) + { + _e_sys_can_suspend = 1; + _e_sys_suspend_check_exe = NULL; + } + _e_sys_exe_pending--; + } + else if ((_e_sys_hibernate_check_exe) && (ev->exe == _e_sys_hibernate_check_exe)) + { + if (ev->exit_code == 0) + { + _e_sys_can_hibernate = 1; + _e_sys_hibernate_check_exe = NULL; + } + _e_sys_exe_pending--; + } + + if (_e_sys_exe_pending <= 0) + { + if (_e_sys_exe_exit_handler) + ecore_event_handler_del(_e_sys_exe_exit_handler); + _e_sys_exe_exit_handler = NULL; + } + return 1; +} diff --git a/src/bin/e_sys.h b/src/bin/e_sys.h new file mode 100644 index 000000000..f4350cc21 --- /dev/null +++ b/src/bin/e_sys.h @@ -0,0 +1,30 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#ifdef E_TYPEDEFS + +typedef enum _E_Sys_Action E_Sys_Action; + +enum _E_Sys_Action +{ + E_SYS_EXIT, + E_SYS_RESTART, + E_SYS_EXIT_NOW, + E_SYS_LOGOUT, + E_SYS_HALT, + E_SYS_REBOOT, + E_SYS_SUSPEND, + E_SYS_HIBERNATE +}; + +#else +#ifndef E_SYS_H +#define E_SYS_H + +EAPI int e_sys_init(void); +EAPI int e_sys_shutdown(void); +EAPI int e_sys_action_possible_get(E_Sys_Action a); +EAPI int e_sys_action_do(E_Sys_Action a, char *param); + +#endif +#endif diff --git a/src/bin/e_sys_main.c b/src/bin/e_sys_main.c new file mode 100644 index 000000000..53a3cb892 --- /dev/null +++ b/src/bin/e_sys_main.c @@ -0,0 +1,232 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* local subsystem functions */ +static int auth_action_ok(char *a); +static int auth_etc_enlightenment_sysactions(char *a, char *u, char *g); +static char *get_word(char *s, char *d); + +/* local subsystem globals */ +Evas_Hash *actions = NULL; + +/* externally accessible functions */ +int +main(int argc, char **argv) +{ + int i; + int test = 0; + char *action, *cmd; + + for (i = 1; i < argc; i++) + { + if ((!strcmp(argv[i], "-h")) || + (!strcmp(argv[i], "-help")) || + (!strcmp(argv[i], "--help"))) + { + printf( + "This is an internal tool for Enlightenment.\n" + "do not use it.\n" + ); + exit(0); + } + } + if (argc == 3) + { + if (!strcmp(argv[1], "-t")) test = 1; + action = argv[2]; + } + else if (argc == 2) + { + action = argv[1]; + } + else + { + exit(-1); + } + + evas_init(); + + if (!auth_action_ok(action)) + { + printf("ERROR: ACTION NOT ALLOWED: %s\n", action); + exit(10); + } + /* we can add more levels of auth here */ + + cmd = evas_hash_find(actions, action); + if (!cmd) + { + printf("ERROR: UNDEFINED ACTION: %s\n", action); + exit(20); + } + if (!test) return system(cmd); + + evas_shutdown(); + + return 0; +} + +/* local subsystem functions */ +static int +auth_action_ok(char *a) +{ + struct passwd *pw; + struct group *gp; + char *usr = NULL, *grp; + int ret; + + pw = getpwuid(getuid()); + if (!pw) return 0; + usr = pw->pw_name; + if (!usr) return 0; + gp = getgrgid(getgid()); + if (gp) grp = gp->gr_name; + /* first stage - check: + * PREFIX/etc/enlightenment/sysactions.conf + */ + ret = auth_etc_enlightenment_sysactions(a, usr, grp); + if (ret == 1) return 1; + else if (ret == -1) return 0; + /* the DEFAULT - allow */ + return 1; +} + +static int +auth_etc_enlightenment_sysactions(char *a, char *u, char *g) +{ + FILE *f; + char file[4096], buf[4096], id[4096], ugname[4096], perm[4096], act[4096]; + char *p, *pp, *s; + int len, line = 0, ok = 0; + int allow = 0; + int deny = 0; + + snprintf(file, sizeof(file), "/etc/enlightenment/sysactions.conf"); + f = fopen(file, "r"); + if (!f) + { + snprintf(file, sizeof(file), PACKAGE_SYSCONF_DIR"/enlightenment/sysactions.conf"); + f = fopen(file, "r"); + if (!f) return 0; + } + while (fgets(buf, sizeof(buf), f)) + { + line++; + len = strlen(buf); + if (len < 1) continue; + if (buf[len - 1] == '\n') buf[len - 1] = 0; + /* format: + * + * # comment + * user: username [allow:|deny:] halt reboot ... + * group: groupname [allow:|deny:] suspend ... + */ + if (buf[0] == '#') continue; + p = buf; + p = get_word(p, id); + p = get_word(p, ugname); + pp = p; + p = get_word(p, perm); + allow = 0; + deny = 0; + if (!strcmp(id, "user:")) + { + if (!fnmatch(u, ugname, 0)) + { + if (!strcmp(perm, "allow:")) allow = 1; + else if (!strcmp(perm, "deny:")) deny = 1; + else + goto malformed; + } + else + continue; + } + else if (!strcmp(id, "group:")) + { + if (!fnmatch(u, ugname, 0)) + { + if (!strcmp(perm, "allow:")) allow = 1; + else if (!strcmp(perm, "deny:")) deny = 1; + else + goto malformed; + } + else + continue; + } + else if (!strcmp(id, "action:")) + { + while ((*pp) && (isspace(*pp))) pp++; + s = evas_hash_find(actions, ugname); + if (s) + { + actions = evas_hash_del(actions, ugname, s); + free(s); + } + actions = evas_hash_add(actions, ugname, strdup(pp)); + continue; + } + else if (id[0] == 0) + continue; + else + goto malformed; + + for (;;) + { + p = get_word(p, act); + if (act[0] == 0) break; + if (!fnmatch(act, a, 0)) + { + if (allow) ok = 1; + else if (deny) ok = -1; + goto done; + } + } + + continue; + malformed: + printf("WARNING: %s:%i\n" + "LINE: '%s'\n" + "MALFORMED LINE. SKIPPED.\n", + file, line, buf); + } + done: + fclose(f); + return ok; +} + +static char * +get_word(char *s, char *d) +{ + char *p1, *p2; + + p1 = s; + p2 = d; + while (*p1) + { + if (p2 == d) + { + if (isspace(*p1)) + { + p1++; + continue; + } + } + if (isspace(*p1)) break; + *p2 = *p1; + p1++; + p2++; + } + *p2 = 0; + return p1; +} + diff --git a/src/bin/e_widget_ilist.c b/src/bin/e_widget_ilist.c index 24db6e0b1..6e09f7adb 100644 --- a/src/bin/e_widget_ilist.c +++ b/src/bin/e_widget_ilist.c @@ -105,6 +105,15 @@ e_widget_ilist_selected_get(Evas_Object *obj) return e_ilist_selected_get(wd->o_ilist); } +EAPI void +e_widget_ilist_unselect(Evas_Object *obj) +{ + E_Widget_Data *wd; + + wd = e_widget_data_get(obj); + e_ilist_unselect(wd->o_ilist); +} + EAPI const char * e_widget_ilist_selected_label_get(Evas_Object *obj) { diff --git a/src/bin/e_widget_ilist.h b/src/bin/e_widget_ilist.h index bcc29add7..fbb79d207 100644 --- a/src/bin/e_widget_ilist.h +++ b/src/bin/e_widget_ilist.h @@ -13,6 +13,7 @@ EAPI void e_widget_ilist_selected_set(Evas_Object *obj, int n); EAPI void e_widget_ilist_selector_set(Evas_Object *obj, int selector); EAPI void e_widget_ilist_go(Evas_Object *obj); EAPI int e_widget_ilist_selected_get(Evas_Object *obj); +EAPI void e_widget_ilist_unselect(Evas_Object *obj); EAPI const char *e_widget_ilist_selected_label_get(Evas_Object *obj); EAPI void e_widget_ilist_remove_num(Evas_Object *obj, int n); EAPI void e_widget_ilist_remove_label(Evas_Object *obj, const char *label); diff --git a/src/modules/battery/e_mod_main.c b/src/modules/battery/e_mod_main.c index dd59bafdb..b07b32896 100644 --- a/src/modules/battery/e_mod_main.c +++ b/src/modules/battery/e_mod_main.c @@ -101,6 +101,7 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) _button_cb_mouse_down, inst); battery_config->instances = evas_list_append(battery_config->instances, inst); battery_config->battery_check_mode = CHECK_NONE; + battery_config->battery_prev_level = -1; battery_config->battery_prev_drain = 1; battery_config->battery_prev_ac = -1; battery_config->battery_prev_battery = -1; @@ -391,14 +392,15 @@ _battery_linux_acpi_check(void) { FILE *f; char *tmp; + int design_cap; + int last_full; snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/info", name); f = fopen(buf, "r"); if (f) { - int design_cap = 0; - int last_full = 0; - + design_cap = 0; + last_full = 0; /* present */ fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0; /* design capacity */ @@ -420,8 +422,6 @@ _battery_linux_acpi_check(void) free(tmp); } fclose(f); - bat_max += design_cap; - bat_filled += last_full; } snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/state", name); f = fopen(buf, "r"); @@ -448,7 +448,7 @@ _battery_linux_acpi_check(void) tmp = _battery_string_get(buf2); if (tmp) { - if (!strcmp(tmp, "unknown")) rate_unknown = 1; + if (!strcmp(tmp, "unknown")) rate_unknown++; else rate = atoi(tmp); free(tmp); } @@ -457,7 +457,7 @@ _battery_linux_acpi_check(void) tmp = _battery_string_get(buf2); if (tmp) { - if (!strcmp(tmp, "unknown")) level_unknown = 1; + if (!strcmp(tmp, "unknown")) level_unknown++; else level = atoi(tmp); free(tmp); } @@ -472,15 +472,18 @@ _battery_linux_acpi_check(void) if (!strcmp(charging_state, "discharging")) { discharging++; - if ((rate == 0) && (rate_unknown == 0)) rate_unknown = 1; + if ((rate == 0) && (rate_unknown == 0)) rate_unknown++; } else if (!strcmp(charging_state, "charging")) { charging++; - if ((rate == 0) && (rate_unknown == 0)) rate_unknown = 1; + if ((rate == 0) && (rate_unknown == 0)) rate_unknown++; } else if (!strcmp(charging_state, "charged")) - rate_unknown = 0; + { +// level = last_full; + rate_unknown--; + } free(charging_state); } E_FREE(capacity_state); @@ -488,17 +491,36 @@ _battery_linux_acpi_check(void) bat_drain += rate; bat_level += level; } + bat_max += design_cap; + bat_filled += last_full; } ecore_list_destroy(bats); } - - if (battery_config->battery_prev_drain < 1) battery_config->battery_prev_drain = 1; - if (bat_drain < 1) bat_drain = battery_config->battery_prev_drain; - battery_config->battery_prev_drain = bat_drain; - + + if ((rate_unknown) && (bat_level != battery_config->battery_prev_level) && + (battery_config->battery_prev_level >= 0)) + { + bat_drain = + ((bat_level - battery_config->battery_prev_level) * 60 * 60) / + battery_config->poll_time; + if (bat_drain < 0) bat_drain = -bat_drain; + if (bat_drain == 0) bat_drain = 1; + rate_unknown = 0; + } + else + { + if (battery_config->battery_prev_drain < 1) + battery_config->battery_prev_drain = 1; + if (bat_drain < 1) + bat_drain = battery_config->battery_prev_drain; + battery_config->battery_prev_drain = bat_drain; + } + if (bat_filled > 0) bat_val = (100 * bat_level) / bat_filled; else bat_val = 100; + battery_config->battery_prev_level = bat_level; + if (discharging) minutes = (60 * bat_level) / bat_drain; else { diff --git a/src/modules/battery/e_mod_main.h b/src/modules/battery/e_mod_main.h index e97247a06..c1bc9500e 100644 --- a/src/modules/battery/e_mod_main.h +++ b/src/modules/battery/e_mod_main.h @@ -28,6 +28,7 @@ struct _Config int battery_prev_drain; int battery_prev_ac; int battery_prev_battery; + int battery_prev_level; }; #ifdef __FreeBSD__ diff --git a/src/modules/cpufreq/Makefile.am b/src/modules/cpufreq/Makefile.am index c7e33340a..5551a3c0c 100644 --- a/src/modules/cpufreq/Makefile.am +++ b/src/modules/cpufreq/Makefile.am @@ -29,7 +29,7 @@ freqset_DATA = \ freqset$(EXEEXT) setuid_root_mode = a=rx,u+s -install-data-hook: +install-exec-hook: @chmod $(setuid_root_mode) $(DESTDIR)$(freqsetdir)/freqset$(EXEEXT) || true noinst_PROGRAMS = freqset diff --git a/src/modules/cpufreq/freqset.c b/src/modules/cpufreq/freqset.c index 655be0193..5f12e7d20 100644 --- a/src/modules/cpufreq/freqset.c +++ b/src/modules/cpufreq/freqset.c @@ -53,29 +53,21 @@ main(int argc, char *argv[]) #else if (!strcmp(argv[1], "frequency")) { - new_frequency = atoi(argv[2]); - - f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", "w"); - if (!f) + if(sys_cpu_setall("scaling_setspeed", argv[2]) == 0) { fprintf(stderr, "Unable to open frequency interface for writing.\n"); return 1; } - fprintf(f, "%d\n", new_frequency); - fclose(f); return 0; } else if (!strcmp(argv[1], "governor")) { - f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "w"); - if (!f) + if(sys_cpu_setall("scaling_governor", argv[2]) == 0) { fprintf(stderr, "Unable to open governor interface for writing.\n"); return 1; } - fprintf(f, "%s\n", argv[2]); - fclose(f); return 0; } @@ -88,3 +80,23 @@ main(int argc, char *argv[]) seteuid(-1); } + +int sys_cpu_setall(const char *control, const char *value) +{ + int num = 0; + char filename[4096]; + FILE *f; + + while(1){ + snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/%s", num, control); + f = fopen(filename, "w"); + + if(!f){ + return(num); + } + fprintf(f, "%s\n", value); + fclose(f); + num++; + } + return -1; +}