1 #include "private.h"
2 
3 #include <Ecore.h>
4 #include <Ecore_Con.h>
5 #include <Ecore_Ipc.h>
6 #include <Eet.h>
7 #include "ipc.h"
8 
9 #define TY_IPC_MAJOR  3
10 #define TY_IPC_MINOR  8
11 
12 static Ecore_Ipc_Server *ipc = NULL;
13 static Ecore_Event_Handler *hnd_data = NULL;
14 static void (*func_new_inst) (Ipc_Instance *inst) = NULL;
15 static Eet_Data_Descriptor *new_inst_edd = NULL;
16 
17 static Eina_Bool
_ipc_cb_client_data(void * _data EINA_UNUSED,int _type EINA_UNUSED,void * event)18 _ipc_cb_client_data(void *_data EINA_UNUSED,
19                     int _type EINA_UNUSED,
20                     void *event)
21 {
22    Ecore_Ipc_Event_Client_Data *e = event;
23 
24    if (ecore_ipc_client_server_get(e->client) != ipc)
25      return ECORE_CALLBACK_PASS_ON;
26    if ((e->major == TY_IPC_MAJOR) &&
27        (e->minor == TY_IPC_MINOR) &&
28        (e->data) && (e->size > 0))
29      {
30         Ipc_Instance *inst;
31 
32         inst = eet_data_descriptor_decode(new_inst_edd, e->data, e->size);
33         if (inst)
34           {
35              if (func_new_inst) func_new_inst(inst);
36              // NOTE strings in inst are part of the inst alloc blob and
37              // don't need separate frees.
38              free(inst);
39           }
40      }
41    return ECORE_CALLBACK_PASS_ON;
42 }
43 
44 static char *
_ipc_hash_get(void)45 _ipc_hash_get(void)
46 {
47    char buf[1024], hash[64] = {};
48    const char *disp, *session, *xdg_session, *xdg_id, *xdg_seat, *xdg_vt;
49    char *s;
50    unsigned int i;
51 
52    /* dumb stoopid hash - i'm feeling lazy */
53    disp = getenv("DISPLAY");
54    if (!disp) disp = "-unknown-";
55    session = getenv("DBUS_SESSION_BUS_ADDRESS");
56    if (!session) session = ":unknown:";
57    xdg_session = getenv("XDG_SESSION_COOKIE");
58    if (!xdg_session) xdg_session = "/unknown/";
59    xdg_id = getenv("XDG_SESSION_ID");
60    if (!xdg_id) xdg_id = "=unknown=";
61    xdg_seat = getenv("XDG_SEAT");
62    if (!xdg_seat) xdg_seat = "@unknown@";
63    xdg_vt = getenv("XDG_VTNR");
64    if (!xdg_vt) xdg_vt = "!unknown!";
65    snprintf(buf, sizeof(buf), "%s.%s.%s.%s.%s.%s",
66             disp, session, xdg_session,
67             xdg_id, xdg_seat, xdg_vt);
68    memcpy(hash, "terminology-", 12);
69    memset(hash+12, 'x', 32);
70    for (i = 0, s = buf; *s; s++)
71      {
72         unsigned char c1, c2;
73 
74         c1 = (((unsigned char)*s) >> 4) & 0xf;
75         c2 = ((unsigned char)*s) & 0x0f;
76         hash[12 + (i % 32)] = (((hash[12 + (i % 32)] - 'a') ^ c1) % 26) + 'a';
77         i++;
78         hash[12 + (i % 32)] = (((hash[12 + (i % 32)] - 'a') ^ c2) % 26) + 'a';
79         i++;
80      }
81    return strdup(hash);
82 }
83 
84 void
ipc_init(void)85 ipc_init(void)
86 {
87    Eet_Data_Descriptor_Class eddc;
88 
89    ecore_ipc_init();
90    eet_init();
91    eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc),
92                                              "inst", sizeof(Ipc_Instance));
93    new_inst_edd = eet_data_descriptor_stream_new(&eddc);
94 
95    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
96                                  "cmd", cmd, EET_T_STRING);
97    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
98                                  "cd", cd, EET_T_STRING);
99    EET_DATA_DESCRIPTOR_ADD_LIST_STRING(new_inst_edd, Ipc_Instance,
100                                        "cmds", cmds);
101    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
102                                  "background", background, EET_T_STRING);
103    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
104                                  "name", name, EET_T_STRING);
105    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
106                                  "theme", theme, EET_T_STRING);
107    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
108                                  "colorscheme", colorscheme, EET_T_STRING);
109    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
110                                  "role", role, EET_T_STRING);
111    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
112                                  "title", title, EET_T_STRING);
113    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
114                                  "icon_name", icon_name, EET_T_STRING);
115    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
116                                  "font", font, EET_T_STRING);
117    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
118                                  "startup_id", startup_id, EET_T_STRING);
119    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
120                                  "x", x, EET_T_INT);
121    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
122                                  "y", y, EET_T_INT);
123    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
124                                  "w", w, EET_T_INT);
125    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
126                                  "h", h, EET_T_INT);
127    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
128                                  "pos", pos, EET_T_INT);
129    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
130                                  "login_shell", login_shell, EET_T_INT);
131    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
132                                  "fullscreen", fullscreen, EET_T_INT);
133    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
134                                  "iconic", iconic, EET_T_INT);
135    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
136                                  "borderless", borderless, EET_T_INT);
137    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
138                                  "override", override, EET_T_INT);
139    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
140                                  "maximized", maximized, EET_T_INT);
141    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
142                                  "hold", hold, EET_T_INT);
143    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
144                                  "nowm", nowm, EET_T_INT);
145    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
146                                  "xterm_256color", xterm_256color, EET_T_INT);
147    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
148                                  "active_links", active_links, EET_T_INT);
149    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
150                                  "video_mute", active_links, EET_T_INT);
151    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
152                                  "cursor_blink", active_links, EET_T_INT);
153    EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
154                                  "visual_bell", active_links, EET_T_INT);
155 }
156 
157 Eina_Bool
ipc_serve(void)158 ipc_serve(void)
159 {
160    char *hash = _ipc_hash_get();
161    if (!hash) return EINA_FALSE;
162    ipc = ecore_ipc_server_add(ECORE_IPC_LOCAL_USER, hash, 0, NULL);
163    free(hash);
164    if (!ipc) return EINA_FALSE;
165    hnd_data = ecore_event_handler_add
166      (ECORE_IPC_EVENT_CLIENT_DATA, _ipc_cb_client_data, NULL);
167    return EINA_TRUE;
168 }
169 
170 void
ipc_shutdown(void)171 ipc_shutdown(void)
172 {
173    if (ipc)
174      {
175         ecore_ipc_server_del(ipc);
176         ipc = NULL;
177      }
178    if (new_inst_edd)
179      {
180         eet_data_descriptor_free(new_inst_edd);
181         new_inst_edd = NULL;
182      }
183    eet_shutdown();
184    ecore_ipc_shutdown();
185    if (hnd_data)
186      {
187         ecore_event_handler_del(hnd_data);
188         hnd_data = NULL;
189      }
190 }
191 
192 void
ipc_instance_new_func_set(void (* func)(Ipc_Instance * inst))193 ipc_instance_new_func_set(void (*func) (Ipc_Instance *inst))
194 {
195    func_new_inst = func;
196 }
197 
198 void
ipc_instance_conn_free(void)199 ipc_instance_conn_free(void)
200 {
201    char *hash = _ipc_hash_get();
202    char *address = ecore_con_local_path_new(EINA_FALSE,
203                                             hash,
204                                             0);
205    errno = 0;
206    unlink(address);
207    ERR("unlinking: '%s': %s", address, strerror(errno));
208    free(address);
209 }
210 
211 Eina_Bool
ipc_instance_add(Ipc_Instance * inst)212 ipc_instance_add(Ipc_Instance *inst)
213 {
214    int size = 0;
215    void *data;
216    char *hash = _ipc_hash_get();
217    Ecore_Ipc_Server *ipcsrv;
218 
219    if (!hash) return EINA_FALSE;
220    data = eet_data_descriptor_encode(new_inst_edd, inst, &size);
221    if (!data)
222      {
223         free(hash);
224         return EINA_FALSE;
225      }
226 
227    ipcsrv = ecore_ipc_server_connect(ECORE_IPC_LOCAL_USER, hash, 0, NULL);
228    if (ipcsrv)
229      {
230         ecore_ipc_server_send(ipcsrv, TY_IPC_MAJOR, TY_IPC_MINOR,
231                               0, 0, 0, data, size);
232         ecore_ipc_server_flush(ipcsrv);
233         free(data);
234         free(hash);
235         ecore_ipc_server_del(ipcsrv);
236         return EINA_TRUE;
237      }
238    else
239      {
240         DBG("connect failed");
241      }
242    free(data);
243    free(hash);
244    return EINA_FALSE;
245 }
246