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