246 lines
8.2 KiB
C
246 lines
8.2 KiB
C
#include "private.h"
|
|
|
|
#include <Ecore.h>
|
|
#include <Ecore_Con.h>
|
|
#include <Ecore_Ipc.h>
|
|
#include <Eet.h>
|
|
#include "ipc.h"
|
|
|
|
#define TY_IPC_MAJOR 3
|
|
#define TY_IPC_MINOR 8
|
|
|
|
static Ecore_Ipc_Server *ipc = NULL;
|
|
static Ecore_Event_Handler *hnd_data = NULL;
|
|
static void (*func_new_inst) (Ipc_Instance *inst) = NULL;
|
|
static Eet_Data_Descriptor *new_inst_edd = NULL;
|
|
|
|
static Eina_Bool
|
|
_ipc_cb_client_data(void *_data EINA_UNUSED,
|
|
int _type EINA_UNUSED,
|
|
void *event)
|
|
{
|
|
Ecore_Ipc_Event_Client_Data *e = event;
|
|
|
|
if (ecore_ipc_client_server_get(e->client) != ipc)
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
if ((e->major == TY_IPC_MAJOR) &&
|
|
(e->minor == TY_IPC_MINOR) &&
|
|
(e->data) && (e->size > 0))
|
|
{
|
|
Ipc_Instance *inst;
|
|
|
|
inst = eet_data_descriptor_decode(new_inst_edd, e->data, e->size);
|
|
if (inst)
|
|
{
|
|
if (func_new_inst) func_new_inst(inst);
|
|
// NOTE strings in inst are part of the inst alloc blob and
|
|
// don't need separate frees.
|
|
free(inst);
|
|
}
|
|
}
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
static char *
|
|
_ipc_hash_get(void)
|
|
{
|
|
char buf[1024], hash[64] = {};
|
|
const char *disp, *session, *xdg_session, *xdg_id, *xdg_seat, *xdg_vt;
|
|
char *s;
|
|
unsigned int i;
|
|
|
|
/* dumb stoopid hash - i'm feeling lazy */
|
|
disp = getenv("DISPLAY");
|
|
if (!disp) disp = "-unknown-";
|
|
session = getenv("DBUS_SESSION_BUS_ADDRESS");
|
|
if (!session) session = ":unknown:";
|
|
xdg_session = getenv("XDG_SESSION_COOKIE");
|
|
if (!xdg_session) xdg_session = "/unknown/";
|
|
xdg_id = getenv("XDG_SESSION_ID");
|
|
if (!xdg_id) xdg_id = "=unknown=";
|
|
xdg_seat = getenv("XDG_SEAT");
|
|
if (!xdg_seat) xdg_seat = "@unknown@";
|
|
xdg_vt = getenv("XDG_VTNR");
|
|
if (!xdg_vt) xdg_vt = "!unknown!";
|
|
snprintf(buf, sizeof(buf), "%s.%s.%s.%s.%s.%s",
|
|
disp, session, xdg_session,
|
|
xdg_id, xdg_seat, xdg_vt);
|
|
memcpy(hash, "terminology-", 12);
|
|
memset(hash+12, 'x', 32);
|
|
for (i = 0, s = buf; *s; s++)
|
|
{
|
|
unsigned char c1, c2;
|
|
|
|
c1 = (((unsigned char)*s) >> 4) & 0xf;
|
|
c2 = ((unsigned char)*s) & 0x0f;
|
|
hash[12 + (i % 32)] = (((hash[12 + (i % 32)] - 'a') ^ c1) % 26) + 'a';
|
|
i++;
|
|
hash[12 + (i % 32)] = (((hash[12 + (i % 32)] - 'a') ^ c2) % 26) + 'a';
|
|
i++;
|
|
}
|
|
return strdup(hash);
|
|
}
|
|
|
|
void
|
|
ipc_init(void)
|
|
{
|
|
Eet_Data_Descriptor_Class eddc;
|
|
|
|
ecore_ipc_init();
|
|
eet_init();
|
|
eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc),
|
|
"inst", sizeof(Ipc_Instance));
|
|
new_inst_edd = eet_data_descriptor_stream_new(&eddc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"cmd", cmd, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"cd", cd, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_LIST_STRING(new_inst_edd, Ipc_Instance,
|
|
"cmds", cmds);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"background", background, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"name", name, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"theme", theme, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"colorscheme", colorscheme, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"role", role, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"title", title, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"icon_name", icon_name, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"font", font, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"startup_id", startup_id, EET_T_STRING);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"x", x, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"y", y, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"w", w, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"h", h, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"pos", pos, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"login_shell", login_shell, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"fullscreen", fullscreen, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"iconic", iconic, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"borderless", borderless, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"override", override, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"maximized", maximized, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"hold", hold, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"nowm", nowm, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"xterm_256color", xterm_256color, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"active_links", active_links, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"video_mute", active_links, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"cursor_blink", active_links, EET_T_INT);
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
|
"visual_bell", active_links, EET_T_INT);
|
|
}
|
|
|
|
Eina_Bool
|
|
ipc_serve(void)
|
|
{
|
|
char *hash = _ipc_hash_get();
|
|
if (!hash) return EINA_FALSE;
|
|
ipc = ecore_ipc_server_add(ECORE_IPC_LOCAL_USER, hash, 0, NULL);
|
|
free(hash);
|
|
if (!ipc) return EINA_FALSE;
|
|
hnd_data = ecore_event_handler_add
|
|
(ECORE_IPC_EVENT_CLIENT_DATA, _ipc_cb_client_data, NULL);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
void
|
|
ipc_shutdown(void)
|
|
{
|
|
if (ipc)
|
|
{
|
|
ecore_ipc_server_del(ipc);
|
|
ipc = NULL;
|
|
}
|
|
if (new_inst_edd)
|
|
{
|
|
eet_data_descriptor_free(new_inst_edd);
|
|
new_inst_edd = NULL;
|
|
}
|
|
eet_shutdown();
|
|
ecore_ipc_shutdown();
|
|
if (hnd_data)
|
|
{
|
|
ecore_event_handler_del(hnd_data);
|
|
hnd_data = NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
ipc_instance_new_func_set(void (*func) (Ipc_Instance *inst))
|
|
{
|
|
func_new_inst = func;
|
|
}
|
|
|
|
void
|
|
ipc_instance_conn_free(void)
|
|
{
|
|
char *hash = _ipc_hash_get();
|
|
char *address = ecore_con_local_path_new(EINA_FALSE,
|
|
hash,
|
|
0);
|
|
errno = 0;
|
|
unlink(address);
|
|
ERR("unlinking: '%s': %s", address, strerror(errno));
|
|
free(address);
|
|
}
|
|
|
|
Eina_Bool
|
|
ipc_instance_add(Ipc_Instance *inst)
|
|
{
|
|
int size = 0;
|
|
void *data;
|
|
char *hash = _ipc_hash_get();
|
|
Ecore_Ipc_Server *ipcsrv;
|
|
|
|
if (!hash) return EINA_FALSE;
|
|
data = eet_data_descriptor_encode(new_inst_edd, inst, &size);
|
|
if (!data)
|
|
{
|
|
free(hash);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
ipcsrv = ecore_ipc_server_connect(ECORE_IPC_LOCAL_USER, hash, 0, NULL);
|
|
if (ipcsrv)
|
|
{
|
|
ecore_ipc_server_send(ipcsrv, TY_IPC_MAJOR, TY_IPC_MINOR,
|
|
0, 0, 0, data, size);
|
|
ecore_ipc_server_flush(ipcsrv);
|
|
free(data);
|
|
free(hash);
|
|
ecore_ipc_server_del(ipcsrv);
|
|
return EINA_TRUE;
|
|
}
|
|
else
|
|
{
|
|
DBG("connect failed");
|
|
}
|
|
free(data);
|
|
free(hash);
|
|
return EINA_FALSE;
|
|
}
|