From 0c3f127c86af818d260966d2292b199757087157 Mon Sep 17 00:00:00 2001 From: Simon Poirier Date: Sat, 11 Jul 2009 21:39:46 +0000 Subject: repackage --- (limited to 'src/sugar/gsm-client-xsmp.c') diff --git a/src/sugar/gsm-client-xsmp.c b/src/sugar/gsm-client-xsmp.c deleted file mode 100644 index 04c7de4..0000000 --- a/src/sugar/gsm-client-xsmp.c +++ /dev/null @@ -1,828 +0,0 @@ -/* client-xsmp.c - * Copyright (C) 2007 Novell, Inc. - * - * 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 of the - * License, 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 - * Lesser 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., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include - -#include "gsm-client-xsmp.h" -#include "gsm-session.h" - -/* FIXME */ -#define GsmDesktopFile "_Gsm_DesktopFile" - -static gboolean client_iochannel_watch (GIOChannel *channel, - GIOCondition condition, - gpointer data); -static gboolean client_protocol_timeout (gpointer data); - -static void set_description (GsmClientXSMP *xsmp); - -static const char *xsmp_get_client_id (GsmClient *client); -static pid_t xsmp_get_pid (GsmClient *client); -static char *xsmp_get_desktop_file (GsmClient *client); -static char *xsmp_get_restart_command (GsmClient *client); -static char *xsmp_get_discard_command (GsmClient *client); -static gboolean xsmp_get_autorestart (GsmClient *client); - -static void xsmp_finalize (GObject *object); -static void xsmp_restart (GsmClient *client, - GError **error); -static void xsmp_save_yourself (GsmClient *client, - gboolean save_state); -static void xsmp_save_yourself_phase2 (GsmClient *client); -static void xsmp_interact (GsmClient *client); -static void xsmp_shutdown_cancelled (GsmClient *client); -static void xsmp_die (GsmClient *client); - -G_DEFINE_TYPE (GsmClientXSMP, gsm_client_xsmp, GSM_TYPE_CLIENT) - -static void -gsm_client_xsmp_init (GsmClientXSMP *xsmp) -{ - ; -} - -static void -gsm_client_xsmp_class_init (GsmClientXSMPClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GsmClientClass *client_class = GSM_CLIENT_CLASS (klass); - - object_class->finalize = xsmp_finalize; - - client_class->get_client_id = xsmp_get_client_id; - client_class->get_pid = xsmp_get_pid; - client_class->get_desktop_file = xsmp_get_desktop_file; - client_class->get_restart_command = xsmp_get_restart_command; - client_class->get_discard_command = xsmp_get_discard_command; - client_class->get_autorestart = xsmp_get_autorestart; - - client_class->restart = xsmp_restart; - client_class->save_yourself = xsmp_save_yourself; - client_class->save_yourself_phase2 = xsmp_save_yourself_phase2; - client_class->interact = xsmp_interact; - client_class->shutdown_cancelled = xsmp_shutdown_cancelled; - client_class->die = xsmp_die; -} - -GsmClientXSMP * -gsm_client_xsmp_new (IceConn ice_conn) -{ - GsmClientXSMP *xsmp; - GIOChannel *channel; - int fd; - - xsmp = g_object_new (GSM_TYPE_CLIENT_XSMP, NULL); - xsmp->props = g_ptr_array_new (); - - xsmp->ice_conn = ice_conn; - xsmp->current_save_yourself = -1; - xsmp->next_save_yourself = -1; - - fd = IceConnectionNumber (ice_conn); - fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC); - - channel = g_io_channel_unix_new (fd); - xsmp->watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_ERR, - client_iochannel_watch, xsmp); - g_io_channel_unref (channel); - - xsmp->protocol_timeout = g_timeout_add_seconds (5, client_protocol_timeout, xsmp); - - set_description (xsmp); - g_debug ("New client '%s'", xsmp->description); - - return xsmp; -} - -static void -xsmp_finalize (GObject *object) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) object; - - g_debug ("xsmp_finalize (%s)", xsmp->description); - - if (xsmp->watch_id) - g_source_remove (xsmp->watch_id); - - if (xsmp->conn) - SmsCleanUp (xsmp->conn); - else - IceCloseConnection (xsmp->ice_conn); - - if (xsmp->protocol_timeout) - g_source_remove (xsmp->protocol_timeout); - - G_OBJECT_CLASS (gsm_client_xsmp_parent_class)->finalize (object); -} - -static gboolean -client_iochannel_watch (GIOChannel *channel, - GIOCondition condition, - gpointer data) -{ - GsmClient *client = data; - GsmClientXSMP *xsmp = data; - - switch (IceProcessMessages (xsmp->ice_conn, NULL, NULL)) - { - case IceProcessMessagesSuccess: - return TRUE; - - case IceProcessMessagesIOError: - g_debug ("IceProcessMessagesIOError on '%s'", xsmp->description); - gsm_client_disconnected (client); - return FALSE; - - case IceProcessMessagesConnectionClosed: - g_debug ("IceProcessMessagesConnectionClosed on '%s'", - xsmp->description); - return FALSE; - - default: - g_assert_not_reached (); - } -} - -/* Called if too much time passes between the initial connection and - * the XSMP protocol setup. - */ -static gboolean -client_protocol_timeout (gpointer data) -{ - GsmClient *client = data; - GsmClientXSMP *xsmp = data; - - g_debug ("client_protocol_timeout for client '%s' in ICE status %d", - xsmp->description, IceConnectionStatus (xsmp->ice_conn)); - gsm_client_disconnected (client); - - return FALSE; -} - -static Status -register_client_callback (SmsConn conn, - SmPointer manager_data, - char *previous_id) -{ - GsmClient *client = manager_data; - GsmClientXSMP *xsmp = manager_data; - char *id; - - g_debug ("Client '%s' received RegisterClient(%s)", - xsmp->description, - previous_id ? previous_id : "NULL"); - - id = gsm_session_register_client (global_session, client, previous_id); - - if (id == NULL) - { - g_debug (" rejected: invalid previous_id"); - free (previous_id); - return FALSE; - } - - xsmp->id = id; - - set_description (xsmp); - - g_debug ("Sending RegisterClientReply to '%s'", xsmp->description); - - SmsRegisterClientReply (conn, xsmp->id); - - if (!previous_id) - { - /* Send the initial SaveYourself. */ - g_debug ("Sending initial SaveYourself"); - SmsSaveYourself (conn, SmSaveLocal, False, SmInteractStyleNone, False); - xsmp->current_save_yourself = SmSaveLocal; - - free (previous_id); - } - - return TRUE; -} - -static void -do_save_yourself (GsmClientXSMP *xsmp, int save_type) -{ - if (xsmp->next_save_yourself != -1) - { - /* Either we're currently doing a shutdown and there's a checkpoint - * queued after it, or vice versa. Either way, the new SaveYourself - * is redundant. - */ - g_debug (" skipping redundant SaveYourself for '%s'", - xsmp->description); - } - else if (xsmp->current_save_yourself != -1) - { - g_debug (" queuing new SaveYourself for '%s'", - xsmp->description); - xsmp->next_save_yourself = save_type; - } - else - { - xsmp->current_save_yourself = save_type; - - switch (save_type) - { - case SmSaveLocal: - /* Save state */ - SmsSaveYourself (xsmp->conn, SmSaveLocal, FALSE, - SmInteractStyleNone, FALSE); - break; - - default: - /* Logout */ - SmsSaveYourself (xsmp->conn, save_type, TRUE, - SmInteractStyleAny, FALSE); - break; - } - } -} - -static void -save_yourself_request_callback (SmsConn conn, - SmPointer manager_data, - int save_type, - Bool shutdown, - int interact_style, - Bool fast, - Bool global) -{ - GsmClientXSMP *xsmp = manager_data; - - g_debug ("Client '%s' received SaveYourselfRequest(%s, %s, %s, %s, %s)", - xsmp->description, - save_type == SmSaveLocal ? "SmSaveLocal" : - save_type == SmSaveGlobal ? "SmSaveGlobal" : "SmSaveBoth", - shutdown ? "Shutdown" : "!Shutdown", - interact_style == SmInteractStyleAny ? "SmInteractStyleAny" : - interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" : - "SmInteractStyleNone", fast ? "Fast" : "!Fast", - global ? "Global" : "!Global"); - - /* Examining the g_debug above, you can see that there are a total - * of 72 different combinations of options that this could have been - * called with. However, most of them are stupid. - * - * If @shutdown and @global are both TRUE, that means the caller is - * requesting that a logout message be sent to all clients, so we do - * that. We use @fast to decide whether or not to show a - * confirmation dialog. (This isn't really what @fast is for, but - * the old gnome-session and ksmserver both interpret it that way, - * so we do too.) We ignore @save_type because we pick the correct - * save_type ourselves later based on user prefs, dialog choices, - * etc, and we ignore @interact_style, because clients have not used - * it correctly consistently enough to make it worth honoring. - * - * If @shutdown is TRUE and @global is FALSE, the caller is - * confused, so we ignore the request. - * - * If @shutdown is FALSE and @save_type is SmSaveGlobal or - * SmSaveBoth, then the client wants us to ask some or all open - * applications to save open files to disk, but NOT quit. This is - * silly and so we ignore the request. - * - * If @shutdown is FALSE and @save_type is SmSaveLocal, then the - * client wants us to ask some or all open applications to update - * their current saved state, but not log out. At the moment, the - * code only supports this for the !global case (ie, a client - * requesting that it be allowed to update *its own* saved state, - * but not having everyone else update their saved state). - */ - - if (shutdown && global) - { - g_debug (" initiating shutdown"); -/* gsm_session_initiate_shutdown (global_session, - !fast, - GSM_SESSION_LOGOUT_TYPE_LOGOUT); -*/ - } - else if (!shutdown && !global) - { - g_debug (" initiating checkpoint"); - do_save_yourself (xsmp, SmSaveLocal); - } - else - g_debug (" ignoring"); -} - -static void -xsmp_restart (GsmClient *client, GError **error) -{ - char *restart_cmd = gsm_client_get_restart_command (client); - - g_spawn_command_line_async (restart_cmd, error); - - g_free (restart_cmd); -} - -static void -xsmp_save_yourself (GsmClient *client, gboolean save_state) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *)client; - - g_debug ("xsmp_save_yourself ('%s', %s)", xsmp->description, - save_state ? "True" : "False"); - - do_save_yourself (xsmp, save_state ? SmSaveBoth : SmSaveGlobal); -} - -static void -save_yourself_phase2_request_callback (SmsConn conn, - SmPointer manager_data) -{ - GsmClient *client = manager_data; - GsmClientXSMP *xsmp = manager_data; - - g_debug ("Client '%s' received SaveYourselfPhase2Request", - xsmp->description); - - if (xsmp->current_save_yourself == SmSaveLocal) - { - /* WTF? Anyway, if it's checkpointing, it doesn't have to wait - * for anyone else. - */ - SmsSaveYourselfPhase2 (xsmp->conn); - } - else - gsm_client_request_phase2 (client); -} - -static void -xsmp_save_yourself_phase2 (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *)client; - - g_debug ("xsmp_save_yourself_phase2 ('%s')", xsmp->description); - - SmsSaveYourselfPhase2 (xsmp->conn); -} - -static void -interact_request_callback (SmsConn conn, - SmPointer manager_data, - int dialog_type) -{ - GsmClient *client = manager_data; - GsmClientXSMP *xsmp = manager_data; - - g_debug ("Client '%s' received InteractRequest(%s)", xsmp->description, - dialog_type == SmInteractStyleAny ? "Any" : "Errors"); - - gsm_client_request_interaction (client); -} - -static void -xsmp_interact (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - - g_debug ("xsmp_interact ('%s')", xsmp->description); - - SmsInteract (xsmp->conn); -} - -static void -interact_done_callback (SmsConn conn, - SmPointer manager_data, - Bool cancel_shutdown) -{ - GsmClient *client = manager_data; - GsmClientXSMP *xsmp = manager_data; - - g_debug ("Client '%s' received InteractDone(cancel_shutdown = %s)", - xsmp->description, cancel_shutdown ? "True" : "False"); - - gsm_client_interaction_done (client, cancel_shutdown); -} - -static void -xsmp_shutdown_cancelled (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - - g_debug ("xsmp_shutdown_cancelled ('%s')", xsmp->description); - - SmsShutdownCancelled (xsmp->conn); -} - -static void -xsmp_die (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - - g_debug ("xsmp_die ('%s')", xsmp->description); - - SmsDie (xsmp->conn); -} - -static void -save_yourself_done_callback (SmsConn conn, - SmPointer manager_data, - Bool success) -{ - GsmClient *client = manager_data; - GsmClientXSMP *xsmp = manager_data; - - g_debug ("Client '%s' received SaveYourselfDone(success = %s)", - xsmp->description, success ? "True" : "False"); - - if (xsmp->current_save_yourself == SmSaveLocal) - { - xsmp->current_save_yourself = -1; - SmsSaveComplete (xsmp->conn); - gsm_client_saved_state (client); - } - else - { - xsmp->current_save_yourself = -1; - gsm_client_save_yourself_done (client); - } - - if (xsmp->next_save_yourself) - { - int save_type = xsmp->next_save_yourself; - - xsmp->next_save_yourself = -1; - do_save_yourself (xsmp, save_type); - } -} - -static void -close_connection_callback (SmsConn conn, - SmPointer manager_data, - int count, - char **reason_msgs) -{ - GsmClient *client = manager_data; - GsmClientXSMP *xsmp = manager_data; - int i; - - g_debug ("Client '%s' received CloseConnection", xsmp->description); - for (i = 0; i < count; i++) - g_debug (" close reason: '%s'", reason_msgs[i]); - SmFreeReasons (count, reason_msgs); - - gsm_client_disconnected (client); -} - -static void -debug_print_property (SmProp *prop) -{ - GString *tmp; - int i; - - switch (prop->type[0]) - { - case 'C': /* CARD8 */ - g_debug (" %s = %d", prop->name, *(unsigned char *)prop->vals[0].value); - break; - - case 'A': /* ARRAY8 */ - g_debug (" %s = '%s'", prop->name, (char *)prop->vals[0].value); - break; - - case 'L': /* LISTofARRAY8 */ - tmp = g_string_new (NULL); - for (i = 0; i < prop->num_vals; i++) - { - g_string_append_printf (tmp, "'%.*s' ", prop->vals[i].length, - (char *)prop->vals[i].value); - } - g_debug (" %s = %s", prop->name, tmp->str); - g_string_free (tmp, TRUE); - break; - - default: - g_debug (" %s = ??? (%s)", prop->name, prop->type); - break; - } -} - -static SmProp * -find_property (GsmClientXSMP *client, const char *name, int *index) -{ - SmProp *prop; - int i; - - for (i = 0; i < client->props->len; i++) - { - prop = client->props->pdata[i]; - - if (!strcmp (prop->name, name)) - { - if (index) - *index = i; - return prop; - } - } - - return NULL; -} - -static void -delete_property (GsmClientXSMP *client, const char *name) -{ - int index; - SmProp *prop; - - prop = find_property (client, name, &index); - if (!prop) - return; - -#if 0 - /* This is wrong anyway; we can't unconditionally run the current - * discard command; if this client corresponds to a GsmAppResumed, - * and the current discard command is identical to the app's - * discard_command, then we don't run the discard command now, - * because that would delete a saved state we may want to resume - * again later. - */ - if (!strcmp (name, SmDiscardCommand)) - gsm_client_run_discard (client); -#endif - - g_ptr_array_remove_index_fast (client->props, index); - SmFreeProperty (prop); -} - -static void -set_properties_callback (SmsConn conn, - SmPointer manager_data, - int num_props, - SmProp **props) -{ - GsmClientXSMP *client = manager_data; - int i; - - g_debug ("Set properties from client '%s'", client->description); - - for (i = 0; i < num_props; i++) - { - delete_property (client, props[i]->name); - g_ptr_array_add (client->props, props[i]); - - debug_print_property (props[i]); - - if (!strcmp (props[i]->name, SmProgram)) - set_description (client); - } - - free (props); - -} - -static void -delete_properties_callback (SmsConn conn, - SmPointer manager_data, - int num_props, - char **prop_names) -{ - GsmClientXSMP *client = manager_data; - int i; - - g_debug ("Delete properties from '%s'", client->description); - - for (i = 0; i < num_props; i++) - { - delete_property (client, prop_names[i]); - - g_debug (" %s", prop_names[i]); - } - - free (prop_names); -} - -static void -get_properties_callback (SmsConn conn, - SmPointer manager_data) -{ - GsmClientXSMP *client = manager_data; - - g_debug ("Get properties request from '%s'", client->description); - - SmsReturnProperties (conn, client->props->len, - (SmProp **)client->props->pdata); -} - -static const char * -xsmp_get_client_id (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - - return xsmp->id; -} - -static pid_t -xsmp_get_pid (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - SmProp *prop = find_property (xsmp, SmProcessID, NULL); - char buf[32]; - - if (!prop || strcmp (prop->type, SmARRAY8) != 0) - return (pid_t)-1; - - /* prop->vals[0].value might not be '\0'-terminated... */ - g_strlcpy (buf, prop->vals[0].value, MIN (prop->vals[0].length, sizeof (buf))); - return (pid_t)strtoul (buf, NULL, 10); -} - -static char * -xsmp_get_desktop_file (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - SmProp *prop = find_property (xsmp, GsmDesktopFile, NULL); - - if (!prop || strcmp (prop->type, SmARRAY8) != 0) - return NULL; - - return g_strndup (prop->vals[0].value, prop->vals[0].length); -} - -static char * -prop_to_command (SmProp *prop) -{ - GString *str; - int i, j; - gboolean need_quotes; - - str = g_string_new (NULL); - for (i = 0; i < prop->num_vals; i++) - { - char *val = prop->vals[i].value; - - need_quotes = FALSE; - for (j = 0; j < prop->vals[i].length; j++) - { - if (!g_ascii_isalnum (val[j]) && !strchr ("-_=:./", val[j])) - { - need_quotes = TRUE; - break; - } - } - - if (i > 0) - g_string_append_c (str, ' '); - - if (!need_quotes) - { - g_string_append_printf (str, "%.*s", prop->vals[i].length, - (char *)prop->vals[i].value); - } - else - { - g_string_append_c (str, '\''); - while (val < (char *)prop->vals[i].value + prop->vals[i].length) - { - if (*val == '\'') - g_string_append (str, "'\''"); - else - g_string_append_c (str, *val); - val++; - } - g_string_append_c (str, '\''); - } - } - - return g_string_free (str, FALSE); -} - -static char * -xsmp_get_restart_command (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - SmProp *prop = find_property (xsmp, SmRestartCommand, NULL); - - if (!prop || strcmp (prop->type, SmLISTofARRAY8) != 0) - return NULL; - - return prop_to_command (prop); -} - -static char * -xsmp_get_discard_command (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - SmProp *prop = find_property (xsmp, SmDiscardCommand, NULL); - - if (!prop || strcmp (prop->type, SmLISTofARRAY8) != 0) - return NULL; - - return prop_to_command (prop); -} - -static gboolean -xsmp_get_autorestart (GsmClient *client) -{ - GsmClientXSMP *xsmp = (GsmClientXSMP *) client; - SmProp *prop = find_property (xsmp, SmRestartStyleHint, NULL); - - if (!prop || strcmp (prop->type, SmCARD8) != 0) - return FALSE; - - return ((unsigned char *)prop->vals[0].value)[0] == SmRestartImmediately; -} - -static void -set_description (GsmClientXSMP *client) -{ - SmProp *prop = find_property (client, SmProgram, NULL); - - g_free (client->description); - if (prop) - { - client->description = g_strdup_printf ("%p [%.*s %s]", client, - prop->vals[0].length, - (char *)prop->vals[0].value, - client->id); - } - else if (client->id) - client->description = g_strdup_printf ("%p [%s]", client, client->id); - else - client->description = g_strdup_printf ("%p", client); -} - -void -gsm_client_xsmp_connect (GsmClientXSMP *client, SmsConn conn, - unsigned long *mask_ret, SmsCallbacks *callbacks_ret) -{ - client->conn = conn; - - if (client->protocol_timeout) - { - g_source_remove (client->protocol_timeout); - client->protocol_timeout = 0; - } - - g_debug ("Initializing client %s", client->description); - - *mask_ret = 0; - - *mask_ret |= SmsRegisterClientProcMask; - callbacks_ret->register_client.callback = register_client_callback; - callbacks_ret->register_client.manager_data = client; - - *mask_ret |= SmsInteractRequestProcMask; - callbacks_ret->interact_request.callback = interact_request_callback; - callbacks_ret->interact_request.manager_data = client; - - *mask_ret |= SmsInteractDoneProcMask; - callbacks_ret->interact_done.callback = interact_done_callback; - callbacks_ret->interact_done.manager_data = client; - - *mask_ret |= SmsSaveYourselfRequestProcMask; - callbacks_ret->save_yourself_request.callback = save_yourself_request_callback; - callbacks_ret->save_yourself_request.manager_data = client; - - *mask_ret |= SmsSaveYourselfP2RequestProcMask; - callbacks_ret->save_yourself_phase2_request.callback = save_yourself_phase2_request_callback; - callbacks_ret->save_yourself_phase2_request.manager_data = client; - - *mask_ret |= SmsSaveYourselfDoneProcMask; - callbacks_ret->save_yourself_done.callback = save_yourself_done_callback; - callbacks_ret->save_yourself_done.manager_data = client; - - *mask_ret |= SmsCloseConnectionProcMask; - callbacks_ret->close_connection.callback = close_connection_callback; - callbacks_ret->close_connection.manager_data = client; - - *mask_ret |= SmsSetPropertiesProcMask; - callbacks_ret->set_properties.callback = set_properties_callback; - callbacks_ret->set_properties.manager_data = client; - - *mask_ret |= SmsDeletePropertiesProcMask; - callbacks_ret->delete_properties.callback = delete_properties_callback; - callbacks_ret->delete_properties.manager_data = client; - - *mask_ret |= SmsGetPropertiesProcMask; - callbacks_ret->get_properties.callback = get_properties_callback; - callbacks_ret->get_properties.manager_data = client; -} -- cgit v0.9.1