/* $Id$ */ /*- * Copyright (c) 2003-2004 Benedikt Meurer * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #include #ifdef HAVE_STRING_H #include #endif #include #include #include #include #include #include #include #define XFSM_CLIENT_MANAGER(c) (XFSM_MANAGER (g_object_get_data (G_OBJECT (c), "--xfsm-manager"))) #ifdef HAVE__ICETRANSNOLISTEN extern void _IceTransNoListen (char *protocol); #endif /* local prototypes */ static Status sm_new_client (SmsConn sms_conn, SmPointer manager_data, unsigned long *mask, SmsCallbacks *callbacks, char **failure_reason); static Status sm_register_client (SmsConn sms_conn, SmPointer client_data, char *previous_id); static void sm_interact_request (SmsConn sms_conn, SmPointer client_data, int dialog_type); static void sm_interact_done (SmsConn sms_conn, SmPointer client_data, Bool cancel_shutdown); static void sm_save_yourself_request (SmsConn sms_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast, Bool global); static void sm_save_yourself_phase2_request(SmsConn sms_conn, SmPointer client_data); static void sm_save_yourself_done (SmsConn sms_conn, SmPointer client_data, Bool success); static void sm_close_connection (SmsConn sms_conn, SmPointer client_data, int num_reasons, char **reasons); static void sm_set_properties (SmsConn sms_conn, SmPointer client_data, int num_props, SmProp **props); static void sm_delete_properties (SmsConn sms_conn, SmPointer client_data, int num_props, char **prop_names); static void sm_get_properties (SmsConn sms_conn, SmPointer client_data); #define SET_CALLBACK(_callbacks, _callback, _client) \ G_STMT_START{ \ _callbacks->_callback.callback = sm_##_callback; \ _callbacks->_callback.manager_data = (SmPointer) _client; \ }G_STMT_END static int num_listeners; static IceListenObj *listen_objs; void sm_init (XfconfChannel *channel, gboolean disable_tcp, XfsmManager *manager) { char *network_idlist; char error[2048]; if (disable_tcp || !xfconf_channel_get_bool (channel, "/security/EnableTcp", FALSE)) { #ifdef HAVE__ICETRANSNOLISTEN _IceTransNoListen ("tcp"); #else fprintf (stderr, "xfce4-session: Requested to disable tcp connections, but " "_IceTransNoListen is not available on this plattform. " "Request will be ignored.\n"); xfsm_verbose ("_IceTransNoListen unavailable on this platform"); #endif } if (!SmsInitialize (PACKAGE, VERSION, sm_new_client, manager, ice_auth_proc, 2048, error)) { fprintf (stderr, "xfce4-session: Unable to register XSM protocol: %s\n", error); /* log to verbose so we don't have to look at both files */ xfsm_verbose ("xfce4-session: Unable to register XSM protocol: %s\n", error); exit (EXIT_FAILURE); } if (!IceListenForConnections (&num_listeners, &listen_objs, 2048, error)) { fprintf (stderr, "xfce4-session: Unable to establish ICE listeners: %s\n", error); /* log to verbose so we don't have to look at both files */ xfsm_verbose ("xfce4-session: Unable to establish ICE listeners: %s\n", error); exit (EXIT_FAILURE); } ice_setup_listeners (num_listeners, listen_objs, manager); network_idlist = IceComposeNetworkIdList (num_listeners, listen_objs); g_setenv ("SESSION_MANAGER", network_idlist, TRUE); free (network_idlist); } static Status sm_new_client (SmsConn sms_conn, SmPointer manager_data, unsigned long *mask, SmsCallbacks *callbacks, char **failure_reason) { XfsmManager *manager = XFSM_MANAGER (manager_data); XfsmClient *client; gchar *error = NULL; xfsm_verbose ("ICE connection fd = %d, received NEW CLIENT\n\n", IceConnectionNumber (SmsGetIceConnection (sms_conn))); client = xfsm_manager_new_client (manager, sms_conn, &error); if (client == NULL) { xfsm_verbose ("NEW CLIENT failed: %s\n", error); #ifdef HAVE_STRDUP *failure_reason = strdup (error); #else *failure_reason = (char *) malloc (strlen (error) + 1); if (*failure_reason != NULL) strcpy (*failure_reason, error); #endif return False; } SET_CALLBACK (callbacks, register_client, client); SET_CALLBACK (callbacks, interact_request, client); SET_CALLBACK (callbacks, interact_done, client); SET_CALLBACK (callbacks, save_yourself_request, client); SET_CALLBACK (callbacks, save_yourself_phase2_request, client); SET_CALLBACK (callbacks, save_yourself_done, client); SET_CALLBACK (callbacks, close_connection, client); SET_CALLBACK (callbacks, set_properties, client); SET_CALLBACK (callbacks, delete_properties, client); SET_CALLBACK (callbacks, get_properties, client); *mask = SmsRegisterClientProcMask | SmsInteractRequestProcMask | SmsInteractDoneProcMask | SmsSaveYourselfRequestProcMask | SmsSaveYourselfP2RequestProcMask | SmsSaveYourselfDoneProcMask | SmsCloseConnectionProcMask | SmsSetPropertiesProcMask | SmsDeletePropertiesProcMask | SmsGetPropertiesProcMask; g_object_set_data (G_OBJECT (client), "--xfsm-manager", manager); return True; } static Status sm_register_client (SmsConn sms_conn, SmPointer client_data, char *previous_id) { XfsmClient *client = (XfsmClient *) client_data; Status result; xfsm_verbose ("ICE connection fd = %d, received REGISTER CLIENT [Previous Id = %s]\n\n", IceConnectionNumber (SmsGetIceConnection (sms_conn)), previous_id != NULL ? previous_id : "None"); result = xfsm_manager_register_client (XFSM_CLIENT_MANAGER (client), client, NULL, previous_id); if (previous_id != NULL) free (previous_id); return result; } static void sm_interact_request (SmsConn sms_conn, SmPointer client_data, int dialog_type) { XfsmClient *client = (XfsmClient *) client_data; xfsm_verbose ("Client Id = %s, received INTERACT REQUEST [Dialog type = %s]\n\n", xfsm_client_get_id (client), dialog_type == SmDialogError ? "Error" : "Normal"); xfsm_manager_interact (XFSM_CLIENT_MANAGER (client), client, dialog_type); } static void sm_interact_done (SmsConn sms_conn, SmPointer client_data, Bool cancel_shutdown) { XfsmClient *client = (XfsmClient *) client_data; xfsm_verbose ("Client Id = %s, received INTERACT DONE [Cancel shutdown = %s]\n\n", xfsm_client_get_id (client), cancel_shutdown ? "True" : "False"); xfsm_manager_interact_done (XFSM_CLIENT_MANAGER (client), client, cancel_shutdown); } static void sm_save_yourself_request (SmsConn sms_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast, Bool global) { XfsmClient *client = (XfsmClient *) client_data; if (G_UNLIKELY (verbose)) { xfsm_verbose ("Client Id = %s, received SAVE YOURSELF REQUEST\n", xfsm_client_get_id (client)); xfsm_verbose (" Save type: %s\n", save_type == SmSaveLocal ? "Local" : (save_type == SmSaveGlobal ? "Global" : "Both")); xfsm_verbose (" Shutdown: %s\n", shutdown ? "True" : "False"); xfsm_verbose (" Interact Style: %s\n", interact_style == SmInteractStyleNone ? "None" : (interact_style == SmInteractStyleErrors ? "Errors" : "Any")); xfsm_verbose (" Fast: %s\n", fast ? "True" : "False"); xfsm_verbose (" Global: %s\n", global ? "True" : "False"); xfsm_verbose ("\n"); } xfsm_manager_save_yourself (XFSM_CLIENT_MANAGER (client), client, save_type, shutdown, interact_style, fast, global); } static void sm_save_yourself_phase2_request (SmsConn sms_conn, SmPointer client_data) { XfsmClient *client = (XfsmClient *) client_data; xfsm_verbose ("Client Id = %s, received SAVE YOURSELF PHASE2 REQUEST\n\n", xfsm_client_get_id (client)); xfsm_manager_save_yourself_phase2 (XFSM_CLIENT_MANAGER (client), client); } static void sm_save_yourself_done (SmsConn sms_conn, SmPointer client_data, Bool success) { XfsmClient *client = (XfsmClient *) client_data; xfsm_verbose ("Client Id = %s, received SAVE YOURSELF DONE [Success = %s]\n\n", xfsm_client_get_id (client), success ? "True" : "False"); xfsm_manager_save_yourself_done (XFSM_CLIENT_MANAGER (client), client, success); } static void sm_close_connection (SmsConn sms_conn, SmPointer client_data, int num_reasons, char **reasons) { XfsmClient *client = (XfsmClient *) client_data; gint n; if (G_UNLIKELY (verbose)) { xfsm_verbose ("Client Id = %s, received CLOSE CONNECTION [Num reasons = %d]\n", xfsm_client_get_id (client), num_reasons); for (n = 0; n < num_reasons; ++n) xfsm_verbose (" Reason %2d: %s\n", n, reasons[n]); xfsm_verbose ("\n"); } xfsm_manager_close_connection (XFSM_CLIENT_MANAGER (client), client, TRUE); if (num_reasons > 0) SmFreeReasons (num_reasons, reasons); } static void sm_set_properties (SmsConn sms_conn, SmPointer client_data, int num_props, SmProp **props) { XfsmClient *client = (XfsmClient *) client_data; int n; int i; if (G_UNLIKELY (verbose)) { xfsm_verbose ("Client Id = %s, received SET PROPERTIES [Num props = %d]\n", xfsm_client_get_id (client), num_props); for (n = 0; n < num_props; ++n) { xfsm_verbose (" Name: %s\n", props[n]->name); xfsm_verbose (" Type: %s\n", props[n]->type); if (strcmp (props[n]->type, "ARRAY8") == 0) { xfsm_verbose (" Value: %s\n", (const gchar *) props[n]->vals->value); } else if (strcmp (props[n]->type, "CARD8") == 0) { const guint8 *cardptr = (const guint8 *) props[n]->vals->value; xfsm_verbose (" Value: %u\n", (unsigned) *cardptr); } else if (strcmp (props[n]->type, "LISTofARRAY8") == 0) { xfsm_verbose (" Value:\n"); for (i = 0; i < props[n]->num_vals; ++i) { xfsm_verbose (" %s%s\n", (const gchar *) props[n]->vals[i].value, (i == props[n]->num_vals - 1) ? "" : ","); } } xfsm_verbose ("\n"); } xfsm_verbose ("\n"); } xfsm_client_merge_properties (client, props, num_props); while (num_props-- > 0) SmFreeProperty (props[num_props]); free (props); } static void sm_delete_properties (SmsConn sms_conn, SmPointer client_data, int num_props, char **prop_names) { XfsmClient *client = (XfsmClient *) client_data; int n; if (G_UNLIKELY (verbose)) { xfsm_verbose ("Client Id = %s, received DELETE PROPERTIES [Num props = %d]\n", xfsm_client_get_id (client), num_props); for (n = 0; n < num_props; ++n) xfsm_verbose (" Name: %s\n", prop_names[n]); xfsm_verbose ("\n"); } xfsm_client_delete_properties (client, prop_names, num_props); while (num_props-- > 0) free (prop_names[num_props]); free (prop_names); } static void sm_get_properties (SmsConn sms_conn, SmPointer client_data) { XfsmClient *client = (XfsmClient *) client_data; XfsmProperties *properties = xfsm_client_get_properties (client); SmProp **props = NULL; gint num_props = 0; xfsm_verbose ("Client Id = %s, received GET PROPERTIES\n\n", properties->client_id); xfsm_properties_extract (properties, &num_props, &props); SmsReturnProperties (sms_conn, num_props, props); if (num_props > 0) { while (num_props-- > 0) SmFreeProperty (props[num_props]); free (props); } }