terminology/src/bin/ipc.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;
}