You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
6.5 KiB
289 lines
6.5 KiB
#include "entrance.h" |
|
|
|
#ifdef STDC_HEADERS |
|
# include <stdlib.h> |
|
# include <stddef.h> |
|
#else |
|
# ifdef HAVE_STDLIB_H |
|
# include <stdlib.h> |
|
# endif |
|
#endif |
|
#ifdef HAVE_ALLOCA_H |
|
# include <alloca.h> |
|
#elif defined __GNUC__ |
|
# define alloca __builtin_alloca |
|
#elif defined _AIX |
|
# define alloca __alloca |
|
#elif defined _MSC_VER |
|
# include <malloc.h> |
|
# define alloca _alloca |
|
#else |
|
# ifndef HAVE_ALLOCA |
|
# ifdef __cplusplus |
|
extern "C" |
|
# endif |
|
void *alloca (size_t); |
|
# endif |
|
#endif |
|
|
|
typedef void (*Entrance_Action_Cb)(void *data); |
|
|
|
static void _entrance_action_shutdown(void *data); |
|
static void _entrance_action_reboot(void *data); |
|
static void _entrance_action_suspend(void *data); |
|
static Eina_Bool _entrance_action_exe_event_del_cb(void *data, int type, void *event); |
|
#ifdef HAVE_GRUB2 |
|
#define GRUB2_FILE "/boot/grub/grub.cfg" |
|
|
|
static void _entrance_action_grub2_get(void); |
|
#endif |
|
|
|
static Eina_List *_entrance_actions = NULL; |
|
|
|
typedef struct Entrance_Action_Data__ |
|
{ |
|
unsigned char id; |
|
const char *label; |
|
Entrance_Action_Cb func; |
|
void *data; |
|
} Entrance_Action_Data; |
|
|
|
static Ecore_Exe *_action_exe = NULL; |
|
|
|
static Entrance_Action_Data * |
|
_entrance_action_add(const char *label, Entrance_Action_Cb func, void *data) |
|
{ |
|
Entrance_Action_Data *ead; |
|
ead = calloc(1, sizeof(Entrance_Action_Data)); |
|
ead->label = eina_stringshare_add(label); |
|
ead->func = func; |
|
ead->data = data; |
|
ead->id = (unsigned char)eina_list_count(_entrance_actions); |
|
ecore_event_handler_add(ECORE_EXE_EVENT_DEL, |
|
_entrance_action_exe_event_del_cb, NULL); |
|
return ead; |
|
} |
|
|
|
|
|
void |
|
entrance_action_init(void) |
|
{ |
|
_entrance_actions = eina_list_append(_entrance_actions, |
|
_entrance_action_add("Shutdown", _entrance_action_shutdown, NULL)); |
|
_entrance_actions = eina_list_append(_entrance_actions, |
|
_entrance_action_add("Reboot", _entrance_action_reboot, NULL)); |
|
_entrance_actions = eina_list_append(_entrance_actions, |
|
_entrance_action_add("Suspend", _entrance_action_suspend, NULL)); |
|
#ifdef HAVE_GRUB2 |
|
_entrance_action_grub2_get(); |
|
#endif |
|
} |
|
|
|
Eina_List * |
|
entrance_action_get(void) |
|
{ |
|
Entrance_Action_Data *ead; |
|
Entrance_Action *ea; |
|
Eina_List *l, *ret = NULL; |
|
|
|
EINA_LIST_FOREACH(_entrance_actions, l, ead) |
|
{ |
|
ea = calloc(1, sizeof(Entrance_Action)); |
|
ea->label = eina_stringshare_add(ead->label); |
|
ea->id = ead->id; |
|
ret = eina_list_append(ret, ea); |
|
} |
|
return ret; |
|
} |
|
|
|
void |
|
entrance_action_shutdown(void) |
|
{ |
|
Entrance_Action_Data *ead; |
|
EINA_LIST_FREE(_entrance_actions, ead) |
|
{ |
|
eina_stringshare_del(ead->label); |
|
free(ead); |
|
} |
|
} |
|
|
|
|
|
void |
|
entrance_action_run(int action) |
|
{ |
|
Entrance_Action_Data *ead; |
|
|
|
ead = eina_list_nth(_entrance_actions, action); |
|
if (ead) |
|
ead->func(ead->data); |
|
} |
|
|
|
static void |
|
_entrance_action_suspend(void *data EINA_UNUSED) |
|
{ |
|
PT("Suspend"); |
|
_action_exe = NULL; |
|
ecore_exe_run(entrance_config->command.suspend, NULL); |
|
} |
|
|
|
static void |
|
_entrance_action_shutdown(void *data EINA_UNUSED) |
|
{ |
|
PT("Shutdown"); |
|
_action_exe = ecore_exe_run(entrance_config->command.shutdown, NULL); |
|
} |
|
|
|
static void |
|
_entrance_action_reboot(void *data EINA_UNUSED) |
|
{ |
|
PT("Reboot\n"); |
|
_action_exe = ecore_exe_run(entrance_config->command.reboot, NULL); |
|
} |
|
|
|
static Eina_Bool |
|
_entrance_action_exe_event_del_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) |
|
{ |
|
Ecore_Exe_Event_Del *ev; |
|
Eina_Bool ret = ECORE_CALLBACK_PASS_ON; |
|
ev = event; |
|
if (!ev->exe) return ret; |
|
if (ev->exe == _action_exe) |
|
{ |
|
PT("action quit requested by user\n"); |
|
ecore_main_loop_quit(); |
|
ret = ECORE_CALLBACK_DONE; |
|
} |
|
return ret; |
|
} |
|
|
|
/* grub2 action */ |
|
#ifdef HAVE_GRUB2 |
|
static void |
|
_entrance_action_grub2(void *data) |
|
{ |
|
size_t i = 0; |
|
char buf[PATH_MAX]; |
|
i = (size_t)data; |
|
|
|
snprintf(buf, sizeof(buf), |
|
"grub-reboot %lu && %s", (unsigned long int) i, entrance_config->command.reboot); |
|
_action_exe = ecore_exe_run(buf, NULL); |
|
|
|
} |
|
|
|
static char * |
|
_entrance_memstr(char *data, size_t length, char *look, unsigned int size) |
|
{ |
|
char *tmp; |
|
|
|
while (length >= size) |
|
{ |
|
tmp = memchr(data, *look, length); |
|
if (!tmp) return NULL; |
|
|
|
if (strncmp(tmp + 1, look + 1, size - 1) == 0) |
|
return tmp; |
|
length = tmp - data; |
|
data = tmp; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
static void |
|
_entrance_action_grub2_get(void) |
|
{ |
|
Eina_File *f; |
|
unsigned char grub2_ok = 0; |
|
size_t menuentry = 0; |
|
char *data; |
|
char *r, *r2; |
|
char *s; |
|
int i; |
|
|
|
PT("trying to open "GRUB2_FILE); |
|
f = eina_file_open(GRUB2_FILE, EINA_FALSE); |
|
if (!f) return ; |
|
fprintf(stderr, " o"); |
|
|
|
data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); |
|
if (!data) goto on_error; |
|
fprintf(stderr, "k\n"); |
|
|
|
s = data; |
|
r2 = NULL; |
|
for (i = eina_file_size_get(f); i > 0; --i, s++) |
|
{ |
|
int size; |
|
|
|
/* working line by line */ |
|
r = memchr(s, '\n', i); |
|
if (!r) |
|
{ |
|
r = s + i; |
|
i = 0; |
|
} |
|
size = r - s; |
|
|
|
if (*s == '#') |
|
goto end_line; |
|
|
|
/* look if the word is in this line */ |
|
if (!grub2_ok) |
|
r2 = _entrance_memstr(s, size, "default=\"${saved_entry}\"", 24); |
|
else |
|
r2 = _entrance_memstr(s, size, "menuentry", 9); |
|
|
|
/* still some lines to read */ |
|
if (!r2) goto end_line; |
|
|
|
if (!grub2_ok) |
|
{ |
|
grub2_ok = 1; |
|
PT("GRUB2 save mode found\n"); |
|
} |
|
else |
|
{ |
|
char *action; |
|
char *local; |
|
char *tmp; |
|
|
|
r2 += 10; |
|
size -= 10; |
|
|
|
tmp = memchr(r2, '\'', size); |
|
if (!tmp) goto end_line; |
|
|
|
size -= tmp - r2 + 1; |
|
r2 = tmp + 1; |
|
tmp = memchr(r2, '\'', size); |
|
if (!tmp) goto end_line; |
|
|
|
local = alloca(tmp - r2 + 1); |
|
memcpy(local, r2, tmp - r2); |
|
local[tmp - r2] = '\0'; |
|
|
|
action = malloc((tmp - r2 + 1 + 11) * sizeof (char)); |
|
if (!action) goto end_line; |
|
|
|
sprintf(action, "Reboot on %s", local); |
|
PT("GRUB2 '%s'\n", action); |
|
_entrance_actions = |
|
eina_list_append(_entrance_actions, |
|
_entrance_action_add(action, |
|
_entrance_action_grub2, |
|
(void*)(menuentry++))); |
|
|
|
} |
|
|
|
end_line: |
|
i -= size; |
|
s = r; |
|
} |
|
|
|
eina_file_map_free(f, data); |
|
on_error: |
|
eina_file_close(f); |
|
} |
|
#endif
|
|
|