1 /* $Id$ */
2 /*-
3 * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org>
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #ifdef HAVE_STDLIB_H
27 #include <stdlib.h>
28 #endif
29 #include <stdio.h>
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33
34 #include <X11/ICE/ICElib.h>
35 #include <X11/SM/SMlib.h>
36
37 #include <libxfce4util/libxfce4util.h>
38
39 #include <xfce4-session/ice-layer.h>
40 #include <xfce4-session/sm-layer.h>
41 #include <xfce4-session/xfsm-global.h>
42 #include <xfce4-session/xfsm-manager.h>
43
44 #define XFSM_CLIENT_MANAGER(c) (XFSM_MANAGER (g_object_get_data (G_OBJECT (c), "--xfsm-manager")))
45
46 #ifdef HAVE__ICETRANSNOLISTEN
47 extern void _IceTransNoListen (char *protocol);
48 #endif
49
50 /* local prototypes */
51 static Status sm_new_client (SmsConn sms_conn,
52 SmPointer manager_data,
53 unsigned long *mask,
54 SmsCallbacks *callbacks,
55 char **failure_reason);
56 static Status sm_register_client (SmsConn sms_conn,
57 SmPointer client_data,
58 char *previous_id);
59 static void sm_interact_request (SmsConn sms_conn,
60 SmPointer client_data,
61 int dialog_type);
62 static void sm_interact_done (SmsConn sms_conn,
63 SmPointer client_data,
64 Bool cancel_shutdown);
65 static void sm_save_yourself_request (SmsConn sms_conn,
66 SmPointer client_data,
67 int save_type,
68 Bool shutdown,
69 int interact_style,
70 Bool fast,
71 Bool global);
72 static void sm_save_yourself_phase2_request(SmsConn sms_conn,
73 SmPointer client_data);
74 static void sm_save_yourself_done (SmsConn sms_conn,
75 SmPointer client_data,
76 Bool success);
77 static void sm_close_connection (SmsConn sms_conn,
78 SmPointer client_data,
79 int num_reasons,
80 char **reasons);
81 static void sm_set_properties (SmsConn sms_conn,
82 SmPointer client_data,
83 int num_props,
84 SmProp **props);
85 static void sm_delete_properties (SmsConn sms_conn,
86 SmPointer client_data,
87 int num_props,
88 char **prop_names);
89 static void sm_get_properties (SmsConn sms_conn,
90 SmPointer client_data);
91
92
93 #define SET_CALLBACK(_callbacks, _callback, _client) \
94 G_STMT_START{ \
95 _callbacks->_callback.callback = sm_##_callback; \
96 _callbacks->_callback.manager_data = (SmPointer) _client; \
97 }G_STMT_END
98
99
100 static int num_listeners;
101 static IceListenObj *listen_objs;
102
103
104 void
sm_init(XfconfChannel * channel,gboolean disable_tcp,XfsmManager * manager)105 sm_init (XfconfChannel *channel,
106 gboolean disable_tcp,
107 XfsmManager *manager)
108 {
109 char *network_idlist;
110 char error[2048];
111
112 if (disable_tcp || !xfconf_channel_get_bool (channel, "/security/EnableTcp", FALSE))
113 {
114 #ifdef HAVE__ICETRANSNOLISTEN
115 _IceTransNoListen ("tcp");
116 #else
117 fprintf (stderr,
118 "xfce4-session: Requested to disable tcp connections, but "
119 "_IceTransNoListen is not available on this plattform. "
120 "Request will be ignored.\n");
121 xfsm_verbose ("_IceTransNoListen unavailable on this platform");
122 #endif
123 }
124
125 if (!SmsInitialize (PACKAGE, VERSION, sm_new_client, manager, ice_auth_proc,
126 2048, error))
127 {
128 fprintf (stderr, "xfce4-session: Unable to register XSM protocol: %s\n", error);
129 /* log to verbose so we don't have to look at both files */
130 xfsm_verbose ("xfce4-session: Unable to register XSM protocol: %s\n", error);
131 exit (EXIT_FAILURE);
132 }
133
134 if (!IceListenForConnections (&num_listeners, &listen_objs, 2048, error))
135 {
136 fprintf (stderr, "xfce4-session: Unable to establish ICE listeners: %s\n", error);
137 /* log to verbose so we don't have to look at both files */
138 xfsm_verbose ("xfce4-session: Unable to establish ICE listeners: %s\n", error);
139 exit (EXIT_FAILURE);
140 }
141
142 ice_setup_listeners (num_listeners, listen_objs, manager);
143
144 network_idlist = IceComposeNetworkIdList (num_listeners, listen_objs);
145 g_setenv ("SESSION_MANAGER", network_idlist, TRUE);
146 free (network_idlist);
147 }
148
149
150 static Status
sm_new_client(SmsConn sms_conn,SmPointer manager_data,unsigned long * mask,SmsCallbacks * callbacks,char ** failure_reason)151 sm_new_client (SmsConn sms_conn,
152 SmPointer manager_data,
153 unsigned long *mask,
154 SmsCallbacks *callbacks,
155 char **failure_reason)
156 {
157 XfsmManager *manager = XFSM_MANAGER (manager_data);
158 XfsmClient *client;
159 gchar *error = NULL;
160
161 xfsm_verbose ("ICE connection fd = %d, received NEW CLIENT\n\n",
162 IceConnectionNumber (SmsGetIceConnection (sms_conn)));
163
164 client = xfsm_manager_new_client (manager, sms_conn, &error);
165 if (client == NULL)
166 {
167 xfsm_verbose ("NEW CLIENT failed: %s\n", error);
168
169 #ifdef HAVE_STRDUP
170 *failure_reason = strdup (error);
171 #else
172 *failure_reason = (char *) malloc (strlen (error) + 1);
173 if (*failure_reason != NULL)
174 strcpy (*failure_reason, error);
175 #endif
176
177 return False;
178 }
179
180 SET_CALLBACK (callbacks, register_client, client);
181 SET_CALLBACK (callbacks, interact_request, client);
182 SET_CALLBACK (callbacks, interact_done, client);
183 SET_CALLBACK (callbacks, save_yourself_request, client);
184 SET_CALLBACK (callbacks, save_yourself_phase2_request, client);
185 SET_CALLBACK (callbacks, save_yourself_done, client);
186 SET_CALLBACK (callbacks, close_connection, client);
187 SET_CALLBACK (callbacks, set_properties, client);
188 SET_CALLBACK (callbacks, delete_properties, client);
189 SET_CALLBACK (callbacks, get_properties, client);
190
191 *mask = SmsRegisterClientProcMask | SmsInteractRequestProcMask
192 | SmsInteractDoneProcMask | SmsSaveYourselfRequestProcMask
193 | SmsSaveYourselfP2RequestProcMask | SmsSaveYourselfDoneProcMask
194 | SmsCloseConnectionProcMask | SmsSetPropertiesProcMask
195 | SmsDeletePropertiesProcMask | SmsGetPropertiesProcMask;
196
197 g_object_set_data (G_OBJECT (client), "--xfsm-manager", manager);
198
199 return True;
200 }
201
202
203 static Status
sm_register_client(SmsConn sms_conn,SmPointer client_data,char * previous_id)204 sm_register_client (SmsConn sms_conn,
205 SmPointer client_data,
206 char *previous_id)
207 {
208 XfsmClient *client = (XfsmClient *) client_data;
209 Status result;
210
211 xfsm_verbose ("ICE connection fd = %d, received REGISTER CLIENT [Previous Id = %s]\n\n",
212 IceConnectionNumber (SmsGetIceConnection (sms_conn)),
213 previous_id != NULL ? previous_id : "None");
214
215 result = xfsm_manager_register_client (XFSM_CLIENT_MANAGER (client), client, NULL, previous_id);
216
217 if (previous_id != NULL)
218 free (previous_id);
219
220 return result;
221 }
222
223
224 static void
sm_interact_request(SmsConn sms_conn,SmPointer client_data,int dialog_type)225 sm_interact_request (SmsConn sms_conn,
226 SmPointer client_data,
227 int dialog_type)
228 {
229 XfsmClient *client = (XfsmClient *) client_data;
230
231 xfsm_verbose ("Client Id = %s, received INTERACT REQUEST [Dialog type = %s]\n\n",
232 xfsm_client_get_id (client), dialog_type == SmDialogError ? "Error" : "Normal");
233
234 xfsm_manager_interact (XFSM_CLIENT_MANAGER (client), client, dialog_type);
235 }
236
237
238 static void
sm_interact_done(SmsConn sms_conn,SmPointer client_data,Bool cancel_shutdown)239 sm_interact_done (SmsConn sms_conn,
240 SmPointer client_data,
241 Bool cancel_shutdown)
242 {
243 XfsmClient *client = (XfsmClient *) client_data;
244
245 xfsm_verbose ("Client Id = %s, received INTERACT DONE [Cancel shutdown = %s]\n\n",
246 xfsm_client_get_id (client), cancel_shutdown ? "True" : "False");
247
248 xfsm_manager_interact_done (XFSM_CLIENT_MANAGER (client), client, cancel_shutdown);
249 }
250
251
252 static void
sm_save_yourself_request(SmsConn sms_conn,SmPointer client_data,int save_type,Bool shutdown,int interact_style,Bool fast,Bool global)253 sm_save_yourself_request (SmsConn sms_conn,
254 SmPointer client_data,
255 int save_type,
256 Bool shutdown,
257 int interact_style,
258 Bool fast,
259 Bool global)
260 {
261 XfsmClient *client = (XfsmClient *) client_data;
262
263 if (G_UNLIKELY (verbose))
264 {
265 xfsm_verbose ("Client Id = %s, received SAVE YOURSELF REQUEST\n",
266 xfsm_client_get_id (client));
267 xfsm_verbose (" Save type: %s\n",
268 save_type == SmSaveLocal ? "Local"
269 : (save_type == SmSaveGlobal ? "Global" : "Both"));
270 xfsm_verbose (" Shutdown: %s\n", shutdown ? "True" : "False");
271 xfsm_verbose (" Interact Style: %s\n",
272 interact_style == SmInteractStyleNone ? "None"
273 : (interact_style == SmInteractStyleErrors ? "Errors" : "Any"));
274 xfsm_verbose (" Fast: %s\n", fast ? "True" : "False");
275 xfsm_verbose (" Global: %s\n", global ? "True" : "False");
276 xfsm_verbose ("\n");
277 }
278
279 xfsm_manager_save_yourself (XFSM_CLIENT_MANAGER (client), client, save_type, shutdown, interact_style, fast, global);
280 }
281
282
283 static void
sm_save_yourself_phase2_request(SmsConn sms_conn,SmPointer client_data)284 sm_save_yourself_phase2_request (SmsConn sms_conn,
285 SmPointer client_data)
286 {
287 XfsmClient *client = (XfsmClient *) client_data;
288
289 xfsm_verbose ("Client Id = %s, received SAVE YOURSELF PHASE2 REQUEST\n\n",
290 xfsm_client_get_id (client));
291
292 xfsm_manager_save_yourself_phase2 (XFSM_CLIENT_MANAGER (client), client);
293 }
294
295
296 static void
sm_save_yourself_done(SmsConn sms_conn,SmPointer client_data,Bool success)297 sm_save_yourself_done (SmsConn sms_conn,
298 SmPointer client_data,
299 Bool success)
300 {
301 XfsmClient *client = (XfsmClient *) client_data;
302
303 xfsm_verbose ("Client Id = %s, received SAVE YOURSELF DONE [Success = %s]\n\n",
304 xfsm_client_get_id (client), success ? "True" : "False");
305
306 xfsm_manager_save_yourself_done (XFSM_CLIENT_MANAGER (client), client, success);
307 }
308
309
310 static void
sm_close_connection(SmsConn sms_conn,SmPointer client_data,int num_reasons,char ** reasons)311 sm_close_connection (SmsConn sms_conn,
312 SmPointer client_data,
313 int num_reasons,
314 char **reasons)
315 {
316 XfsmClient *client = (XfsmClient *) client_data;
317 gint n;
318
319 if (G_UNLIKELY (verbose))
320 {
321 xfsm_verbose ("Client Id = %s, received CLOSE CONNECTION [Num reasons = %d]\n",
322 xfsm_client_get_id (client), num_reasons);
323 for (n = 0; n < num_reasons; ++n)
324 xfsm_verbose (" Reason %2d: %s\n", n, reasons[n]);
325 xfsm_verbose ("\n");
326 }
327
328 xfsm_manager_close_connection (XFSM_CLIENT_MANAGER (client), client, TRUE);
329
330 if (num_reasons > 0)
331 SmFreeReasons (num_reasons, reasons);
332 }
333
334
335 static void
sm_set_properties(SmsConn sms_conn,SmPointer client_data,int num_props,SmProp ** props)336 sm_set_properties (SmsConn sms_conn,
337 SmPointer client_data,
338 int num_props,
339 SmProp **props)
340 {
341 XfsmClient *client = (XfsmClient *) client_data;
342 int n;
343 int i;
344
345 if (G_UNLIKELY (verbose))
346 {
347 xfsm_verbose ("Client Id = %s, received SET PROPERTIES [Num props = %d]\n",
348 xfsm_client_get_id (client), num_props);
349 for (n = 0; n < num_props; ++n)
350 {
351 xfsm_verbose (" Name: %s\n", props[n]->name);
352 xfsm_verbose (" Type: %s\n", props[n]->type);
353 if (strcmp (props[n]->type, "ARRAY8") == 0)
354 {
355 xfsm_verbose (" Value: %s\n", (const gchar *) props[n]->vals->value);
356 }
357 else if (strcmp (props[n]->type, "CARD8") == 0)
358 {
359 const guint8 *cardptr = (const guint8 *) props[n]->vals->value;
360 xfsm_verbose (" Value: %u\n", (unsigned) *cardptr);
361 }
362 else if (strcmp (props[n]->type, "LISTofARRAY8") == 0)
363 {
364 xfsm_verbose (" Value:\n");
365 for (i = 0; i < props[n]->num_vals; ++i)
366 {
367 xfsm_verbose (" %s%s\n", (const gchar *) props[n]->vals[i].value,
368 (i == props[n]->num_vals - 1) ? "" : ",");
369 }
370 }
371 xfsm_verbose ("\n");
372 }
373 xfsm_verbose ("\n");
374 }
375
376 xfsm_client_merge_properties (client, props, num_props);
377
378 while (num_props-- > 0)
379 SmFreeProperty (props[num_props]);
380 free (props);
381 }
382
383
384 static void
sm_delete_properties(SmsConn sms_conn,SmPointer client_data,int num_props,char ** prop_names)385 sm_delete_properties (SmsConn sms_conn,
386 SmPointer client_data,
387 int num_props,
388 char **prop_names)
389 {
390 XfsmClient *client = (XfsmClient *) client_data;
391 int n;
392
393 if (G_UNLIKELY (verbose))
394 {
395 xfsm_verbose ("Client Id = %s, received DELETE PROPERTIES [Num props = %d]\n",
396 xfsm_client_get_id (client), num_props);
397 for (n = 0; n < num_props; ++n)
398 xfsm_verbose (" Name: %s\n", prop_names[n]);
399 xfsm_verbose ("\n");
400 }
401
402 xfsm_client_delete_properties (client, prop_names, num_props);
403
404 while (num_props-- > 0)
405 free (prop_names[num_props]);
406 free (prop_names);
407 }
408
409
410 static void
sm_get_properties(SmsConn sms_conn,SmPointer client_data)411 sm_get_properties (SmsConn sms_conn,
412 SmPointer client_data)
413 {
414 XfsmClient *client = (XfsmClient *) client_data;
415 XfsmProperties *properties = xfsm_client_get_properties (client);
416 SmProp **props = NULL;
417 gint num_props = 0;
418
419 xfsm_verbose ("Client Id = %s, received GET PROPERTIES\n\n", properties->client_id);
420
421 xfsm_properties_extract (properties, &num_props, &props);
422
423 SmsReturnProperties (sms_conn, num_props, props);
424
425 if (num_props > 0)
426 {
427 while (num_props-- > 0)
428 SmFreeProperty (props[num_props]);
429 free (props);
430 }
431 }
432