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