# HG changeset patch # User Mark Doliner # Date 1133158806 0 # Node ID b7a51e68d0b8f0d46825c14aed0867cc36f87ae3 # Parent 465ddcb3e9e8fd453b63624d20e28632fe08a502 [gaim-migrate @ 14548] Make some things static and namespace session_init and session_end committer: Tailor Script diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/gtkblist.c --- a/src/gtkblist.c Mon Nov 28 05:28:01 2005 +0000 +++ b/src/gtkblist.c Mon Nov 28 06:20:06 2005 +0000 @@ -5446,7 +5446,8 @@ } } -void sortmethod_act(GtkCheckMenuItem *checkmenuitem, char *id) +static void +sortmethod_act(GtkCheckMenuItem *checkmenuitem, char *id) { if (gtk_check_menu_item_get_active(checkmenuitem)) { diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/gtkdialogs.h --- a/src/gtkdialogs.h Mon Nov 28 05:28:01 2005 +0000 +++ b/src/gtkdialogs.h Mon Nov 28 06:20:06 2005 +0000 @@ -54,9 +54,4 @@ gtk_window_set_type_hint(GTK_WINDOW(x), GDK_WINDOW_TYPE_HINT_DIALOG) #define GAIM_WINDOW_ICONIFIED(x) (gdk_window_get_state(GTK_WIDGET(x)->window) & GDK_WINDOW_STATE_ICONIFIED) -/* Functions in session.c */ -extern void session_init(gchar *, gchar *, gchar *); -extern void session_end(); - - #endif /* _GAIM_GTKDIALOGS_H_ */ diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/gtkmain.c --- a/src/gtkmain.c Mon Nov 28 05:28:01 2005 +0000 +++ b/src/gtkmain.c Mon Nov 28 06:20:06 2005 +0000 @@ -58,6 +58,7 @@ #include "gtkrequest.h" #include "gtkroomlist.h" #include "gtksavedstatuses.h" +#include "gtksession.h" #include "gtksound.h" #include "gtkthemes.h" #include "gtkutils.h" @@ -280,7 +281,7 @@ { #ifdef USE_SM /* unplug */ - session_end(); + gaim_gtk_session_end(); #endif /* Save the plugins we have loaded for next time. */ @@ -647,7 +648,7 @@ ui_main(); #ifdef USE_SM - session_init(argv[0], opt_session_arg, opt_config_dir_arg); + gaim_gtk_session_init(argv[0], opt_session_arg, opt_config_dir_arg); #endif if (opt_session_arg != NULL) { g_free(opt_session_arg); diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/gtkplugin.c --- a/src/gtkplugin.c Mon Nov 28 05:28:01 2005 +0000 +++ b/src/gtkplugin.c Mon Nov 28 06:20:06 2005 +0000 @@ -31,6 +31,8 @@ #include +#define GAIM_RESPONSE_CONFIGURE 98121 + static GtkWidget *plugin_dialog = NULL; static GtkWidget *plugin_details = NULL; static GtkWidget *pref_button = NULL; @@ -206,8 +208,8 @@ g_free(description); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - 0, gaim_plugin_is_loaded(plug), + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + 0, gaim_plugin_is_loaded(plug), -1); gtk_tree_path_free(path); @@ -217,7 +219,7 @@ static gboolean ensure_plugin_visible(void *data) { GtkTreeSelection *sel = GTK_TREE_SELECTION(data); - GtkTreeView *tv = gtk_tree_selection_get_tree_view(sel); + GtkTreeView *tv = gtk_tree_selection_get_tree_view(sel); GtkTreeModel *model = gtk_tree_view_get_model(tv); GtkTreePath *path; GtkTreeIter iter; @@ -301,7 +303,7 @@ } plugin_dialog = NULL; break; - case 98121: + case GAIM_RESPONSE_CONFIGURE: if (! gtk_tree_selection_get_selected (sel, &model, &iter)) return; gtk_tree_model_get_value (model, &iter, 2, &val); @@ -346,14 +348,14 @@ if (!gtk_tree_selection_get_selected(sel, &model, &iter)) return; - + gtk_tree_model_get(model, &iter, 2, &plugin, -1); if (!gaim_plugin_is_loaded(plugin)) return; /* Now show the pref-dialog for the plugin */ - plugin_dialog_response_cb(NULL, 98121, sel); + plugin_dialog_response_cb(NULL, GAIM_RESPONSE_CONFIGURE, sel); } void gaim_gtk_plugin_dialog_show() @@ -375,8 +377,10 @@ NULL, GTK_DIALOG_NO_SEPARATOR, NULL); - pref_button = gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), GTK_STOCK_PREFERENCES, 98121); - gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); + pref_button = gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), + _("_Configure Plugin"), GAIM_RESPONSE_CONFIGURE); + gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); gtk_widget_set_sensitive(pref_button, FALSE); gtk_window_set_role(GTK_WINDOW(plugin_dialog), "plugins"); @@ -408,7 +412,7 @@ gtk_tree_view_column_set_sort_column_id(col, 0); g_signal_connect (G_OBJECT(rend), "toggled", G_CALLBACK(plugin_load), ls); - + rendt = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new_with_attributes (_("Name"), rendt, @@ -422,7 +426,7 @@ gtk_tree_view_column_set_sort_column_id(col, 1); g_object_unref(G_OBJECT(ls)); gtk_container_add(GTK_CONTAINER(sw), event_view); - + expander = gtk_expander_new(_("Plugin Details")); gtk_expander_set_use_markup(GTK_EXPANDER(expander), TRUE); plugin_details = gtk_label_new(NULL); diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/gtksavedstatuses.c --- a/src/gtksavedstatuses.c Mon Nov 28 05:28:01 2005 +0000 +++ b/src/gtksavedstatuses.c Mon Nov 28 06:20:06 2005 +0000 @@ -1194,7 +1194,7 @@ return FALSE; } -void +static void substatus_editor_cancel_cb(GtkButton *button, gpointer user_data) { SubStatusEditor *dialog = user_data; @@ -1234,7 +1234,7 @@ return FALSE; } -void +static void substatus_editor_ok_cb(GtkButton *button, gpointer user_data) { SubStatusEditor *dialog = user_data; @@ -1452,7 +1452,8 @@ * Utilities * **************************************************************************/ -void status_menu_cb(GtkComboBox *widget, void(*callback)(GaimSavedStatus*)) +static void +status_menu_cb(GtkComboBox *widget, void(*callback)(GaimSavedStatus*)) { GtkTreeIter iter; gchar *title = NULL; @@ -1487,7 +1488,7 @@ i++; } } - + gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), index); g_signal_connect(G_OBJECT(combobox), "changed", G_CALLBACK(status_menu_cb), callback); return combobox; diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/gtksession.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gtksession.c Mon Nov 28 06:20:06 2005 +0000 @@ -0,0 +1,399 @@ +/* + * @file gtksession.c X Windows session management API + * @ingroup gtkui + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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 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 + * + */ +#include "internal.h" + +#include "core.h" +#include "debug.h" +#include "eventloop.h" + +#ifdef USE_SM + +#include +#include +#include +#include +#include + +#define ERROR_LENGTH 512 + +static IceIOErrorHandler ice_installed_io_error_handler; +static SmcConn session = NULL; +static gchar *myself = NULL; +static gboolean had_first_save = FALSE; +static gboolean session_managed = FALSE; + +/* ICE belt'n'braces stuff */ + +struct ice_connection_info { + IceConn connection; + guint input_id; +}; + +static void ice_process_messages(gpointer data, gint fd, + GaimInputCondition condition) { + struct ice_connection_info *conninfo = (struct ice_connection_info*) data; + IceProcessMessagesStatus status; + + /* please don't block... please! */ + status = IceProcessMessages(conninfo->connection, NULL, NULL); + + if (status == IceProcessMessagesIOError) { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "ICE IO error, closing connection... "); + + /* IO error, please disconnect */ + IceSetShutdownNegotiation(conninfo->connection, False); + IceCloseConnection(conninfo->connection); + + gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); + + /* cancel the handler */ + gaim_input_remove(conninfo->input_id); + } +} + +static void ice_connection_watch(IceConn connection, IcePointer client_data, + Bool opening, IcePointer *watch_data) { + struct ice_connection_info *conninfo = NULL; + + if (opening) { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Handling new ICE connection... "); + + /* ensure ICE connection is not passed to child processes */ + fcntl(IceConnectionNumber(connection), F_SETFD, FD_CLOEXEC); + + conninfo = g_new(struct ice_connection_info, 1); + conninfo->connection = connection; + + /* watch the connection */ + conninfo->input_id = gaim_input_add(IceConnectionNumber(connection), GAIM_INPUT_READ, + ice_process_messages, conninfo); + *watch_data = conninfo; + } else { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Handling closed ICE connection... "); + + /* get the input ID back and stop watching it */ + conninfo = (struct ice_connection_info*) *watch_data; + gaim_input_remove(conninfo->input_id); + g_free(conninfo); + } + + gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); +} + +/* We call any handler installed before (or after) ice_init but + * avoid calling the default libICE handler which does an exit(). + * + * This means we do nothing by default, which is probably correct, + * the connection will get closed by libICE + */ + +static void ice_io_error_handler(IceConn connection) { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Handling ICE IO error... "); + + if (ice_installed_io_error_handler) + (*ice_installed_io_error_handler)(connection); + + gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); +} + +static void ice_init() { + IceIOErrorHandler default_handler; + + ice_installed_io_error_handler = IceSetIOErrorHandler(NULL); + default_handler = IceSetIOErrorHandler(ice_io_error_handler); + + if (ice_installed_io_error_handler == default_handler) + ice_installed_io_error_handler = NULL; + + IceAddConnectionWatch(ice_connection_watch, NULL); + + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "ICE initialized.\n"); +} + +/* my magic utility function */ + +static gchar **session_make_command(gchar *client_id, gchar *config_dir) { + gint i = 2; + gint j = 0; + gchar **ret; + + if (client_id) i += 2; + if (config_dir) i += 2; /* we will specify gaim's user dir */ + + ret = g_new(gchar *, i); + ret[j++] = g_strdup(myself); + + if (client_id) { + ret[j++] = g_strdup("--session"); + ret[j++] = g_strdup(client_id); + } + + if (config_dir) { + ret[j++] = g_strdup("--config"); + ret[j++] = g_strdup(config_dir); + } + + ret[j++] = NULL; + + return ret; +} + +/* SM callback handlers */ + +static void session_save_yourself(SmcConn conn, SmPointer data, int save_type, + Bool shutdown, int interact_style, Bool fast) { + if (had_first_save == FALSE && save_type == SmSaveLocal && + interact_style == SmInteractStyleNone && !shutdown && + !fast) { + /* this is just a dry run, spit it back */ + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Received first save_yourself\n"); + SmcSaveYourselfDone(conn, True); + had_first_save = TRUE; + return; + } + + /* tum ti tum... don't add anything else here without * + * reading SMlib.PS from an X.org ftp server near you */ + + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Received save_yourself\n"); + + if (save_type == SmSaveGlobal || save_type == SmSaveBoth) { + /* may as well do something ... */ + /* or not -- save_prefs(); */ + } + + SmcSaveYourselfDone(conn, True); +} + +static void session_die(SmcConn conn, SmPointer data) { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Received die\n"); + gaim_core_quit(); +} + +static void session_save_complete(SmcConn conn, SmPointer data) { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Received save_complete\n"); +} + +static void session_shutdown_cancelled(SmcConn conn, SmPointer data) { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Received shutdown_cancelled\n"); +} + +/* utility functions stolen from Gnome-client */ + +static void session_set_value(SmcConn conn, gchar *name, char *type, + int num_vals, SmPropValue *vals) { + SmProp *proplist[1]; + SmProp prop; + + g_return_if_fail(conn); + + prop.name = name; + prop.type = type; + prop.num_vals = num_vals; + prop.vals = vals; + + proplist[0] = ∝ + SmcSetProperties(conn, 1, proplist); +} + +static void session_set_string(SmcConn conn, gchar *name, gchar *value) { + SmPropValue val; + + g_return_if_fail(name); + + val.length = strlen (value)+1; + val.value = value; + + session_set_value(conn, name, SmARRAY8, 1, &val); +} + +static void session_set_gchar(SmcConn conn, gchar *name, gchar value) { + SmPropValue val; + + g_return_if_fail(name); + + val.length = 1; + val.value = &value; + + session_set_value(conn, name, SmCARD8, 1, &val); +} + +static void session_set_array(SmcConn conn, gchar *name, gchar *array[]) { + gint argc; + gchar **ptr; + gint i; + + SmPropValue *vals; + + g_return_if_fail (name); + + /* We count the number of elements in our array. */ + for (ptr = array, argc = 0; *ptr ; ptr++, argc++) /* LOOP */; + + /* Now initialize the 'vals' array. */ + vals = g_new (SmPropValue, argc); + for (ptr = array, i = 0 ; i < argc ; ptr++, i++) { + vals[i].length = strlen (*ptr); + vals[i].value = *ptr; + } + + session_set_value(conn, name, SmLISTofARRAY8, argc, vals); + + g_free (vals); +} + +#endif /* USE_SM */ + +/* setup functions */ + +void +gaim_gtk_session_init(gchar *argv0, gchar *previous_id, gchar *config_dir) +{ +#ifdef USE_SM + SmcCallbacks callbacks; + gchar *client_id = NULL; + gchar error[ERROR_LENGTH] = ""; + gchar *tmp = NULL; + gchar **cmd = NULL; + + if (session != NULL) { + /* session is already established, what the hell is going on? */ + gaim_debug(GAIM_DEBUG_WARNING, "Session Management", + "Duplicated call to gaim_gtk_session_init!\n"); + return; + } + + if (g_getenv("SESSION_MANAGER") == NULL) { + gaim_debug(GAIM_DEBUG_ERROR, "Session Management", + "No SESSION_MANAGER found, aborting.\n"); + return; + } + + ice_init(); + + callbacks.save_yourself.callback = session_save_yourself; + callbacks.die.callback = session_die; + callbacks.save_complete.callback = session_save_complete; + callbacks.shutdown_cancelled.callback = session_shutdown_cancelled; + + callbacks.save_yourself.client_data = NULL; + callbacks.die.client_data = NULL; + callbacks.save_complete.client_data = NULL; + callbacks.shutdown_cancelled.client_data = NULL; + + if (previous_id) { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Connecting with previous ID %s\n", previous_id); + } else { + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Connecting with no previous ID\n"); + } + + session = SmcOpenConnection(NULL, "session", SmProtoMajor, SmProtoMinor, SmcSaveYourselfProcMask | + SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, + &callbacks, previous_id, &client_id, ERROR_LENGTH, error); + + if (session == NULL) { + if (error[0] != '\0') { + gaim_debug(GAIM_DEBUG_ERROR, "Session Management", + "Connection failed with error: %s\n", error); + } else { + gaim_debug(GAIM_DEBUG_ERROR, "Session Management", + "Connetion failed with unknown error.\n"); + } + return; + } + + tmp = SmcVendor(session); + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Connected to manager (%s) with client ID %s\n", + tmp, client_id); + g_free(tmp); + + session_managed = TRUE; + gdk_set_sm_client_id(client_id); + + tmp = g_get_current_dir(); + session_set_string(session, SmCurrentDirectory, tmp); + g_free(tmp); + + tmp = g_strdup_printf("%d", (int) getpid()); + session_set_string(session, SmProcessID, tmp); + g_free(tmp); + + tmp = g_strdup(g_get_user_name()); + session_set_string(session, SmUserID, tmp); + g_free(tmp); + + session_set_gchar(session, SmRestartStyleHint, (gchar) SmRestartIfRunning); + session_set_string(session, SmProgram, g_get_prgname()); + + myself = g_strdup(argv0); + gaim_debug(GAIM_DEBUG_MISC, "Session Management", + "Using %s as command\n", myself); + + cmd = session_make_command(NULL, config_dir); + session_set_array(session, SmCloneCommand, cmd); + g_strfreev(cmd); + + /* this is currently useless, but gnome-session warns 'the following applications will not + save their current status' bla bla if we don't have it and the user checks 'Save Session' + when they log out */ + cmd = g_new(gchar *, 2); + cmd[0] = g_strdup("/bin/true"); + cmd[1] = NULL; + session_set_array(session, SmDiscardCommand, cmd); + g_strfreev(cmd); + + cmd = session_make_command(client_id, config_dir); + session_set_array(session, SmRestartCommand, cmd); + g_strfreev(cmd); + + g_free(client_id); +#endif /* USE_SM */ +} + +void +gaim_gtk_session_end() +{ +#ifdef USE_SM + if (session == NULL) /* no session to close */ + return; + + SmcCloseConnection(session, 0, NULL); + + gaim_debug(GAIM_DEBUG_INFO, "Session Management", + "Connection closed.\n"); +#endif /* USE_SM */ +} diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/gtksession.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gtksession.h Mon Nov 28 06:20:06 2005 +0000 @@ -0,0 +1,45 @@ +/** + * @file gtksession.h X Windows session management API + * @ingroup gtkui + * + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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 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 + */ +#ifndef _GAIM_GTKSESSION_H_ +#define _GAIM_GTKSESSION_H_ + +/**************************************************************************/ +/** @name X Windows session subsystem */ +/**************************************************************************/ +/*@{*/ + +/** + * TODO + */ +void gaim_gtk_session_init(gchar *argv0, gchar *previous_id, gchar *config_dir); + +/** + * TODO + */ +void gaim_gtk_session_end(); + +/*@}*/ + +#endif /* _GAIM_GTKSESSION_H_ */ diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/proxy.c --- a/src/proxy.c Mon Nov 28 05:28:01 2005 +0000 +++ b/src/proxy.c Mon Nov 28 06:20:06 2005 +0000 @@ -52,7 +52,7 @@ static void try_connect(struct PHB *); -const char* socks5errors[] = { +static const char *socks5errors[] = { "succeeded\n", "general SOCKS server failure\n", "connection not allowed by ruleset\n", @@ -271,7 +271,7 @@ static int number_of_dns_children = 0; -const int MAX_DNS_CHILDREN = 2; +static const int MAX_DNS_CHILDREN = 2; typedef struct { char hostname[512]; diff -r 465ddcb3e9e8 -r b7a51e68d0b8 src/session.c --- a/src/session.c Mon Nov 28 05:28:01 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,394 +0,0 @@ -/* - * session management for Gaim - * - * Gaim is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 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 - * - */ -#include "internal.h" - -#include "core.h" -#include "debug.h" -#include "eventloop.h" - -#ifdef USE_SM - -#include -#include -#include -#include -#include - -#define ERROR_LENGTH 512 - -static IceIOErrorHandler ice_installed_io_error_handler; -static SmcConn session = NULL; -static gchar *myself = NULL; -static gboolean had_first_save = FALSE; -gboolean session_managed = FALSE; - -/* ICE belt'n'braces stuff */ - -struct ice_connection_info { - IceConn connection; - guint input_id; -}; - -static void ice_process_messages(gpointer data, gint fd, - GaimInputCondition condition) { - struct ice_connection_info *conninfo = (struct ice_connection_info*) data; - IceProcessMessagesStatus status; - - /* please don't block... please! */ - status = IceProcessMessages(conninfo->connection, NULL, NULL); - - if (status == IceProcessMessagesIOError) { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "ICE IO error, closing connection... "); - - /* IO error, please disconnect */ - IceSetShutdownNegotiation(conninfo->connection, False); - IceCloseConnection(conninfo->connection); - - gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); - - /* cancel the handler */ - gaim_input_remove(conninfo->input_id); - } -} - -static void ice_connection_watch(IceConn connection, IcePointer client_data, - Bool opening, IcePointer *watch_data) { - struct ice_connection_info *conninfo = NULL; - - if (opening) { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Handling new ICE connection... "); - - /* ensure ICE connection is not passed to child processes */ - fcntl(IceConnectionNumber(connection), F_SETFD, FD_CLOEXEC); - - conninfo = g_new(struct ice_connection_info, 1); - conninfo->connection = connection; - - /* watch the connection */ - conninfo->input_id = gaim_input_add(IceConnectionNumber(connection), GAIM_INPUT_READ, - ice_process_messages, conninfo); - *watch_data = conninfo; - } else { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Handling closed ICE connection... "); - - /* get the input ID back and stop watching it */ - conninfo = (struct ice_connection_info*) *watch_data; - gaim_input_remove(conninfo->input_id); - g_free(conninfo); - } - - gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); -} - -/* We call any handler installed before (or after) ice_init but - * avoid calling the default libICE handler which does an exit(). - * - * This means we do nothing by default, which is probably correct, - * the connection will get closed by libICE - */ - -static void ice_io_error_handler(IceConn connection) { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Handling ICE IO error... "); - - if (ice_installed_io_error_handler) - (*ice_installed_io_error_handler)(connection); - - gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); -} - -static void ice_init() { - IceIOErrorHandler default_handler; - - ice_installed_io_error_handler = IceSetIOErrorHandler(NULL); - default_handler = IceSetIOErrorHandler(ice_io_error_handler); - - if (ice_installed_io_error_handler == default_handler) - ice_installed_io_error_handler = NULL; - - IceAddConnectionWatch(ice_connection_watch, NULL); - - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "ICE initialized.\n"); -} - -/* my magic utility function */ - -static gchar **session_make_command(gchar *client_id, gchar *config_dir) { - gint i = 2; - gint j = 0; - gchar **ret; - - if (client_id) i += 2; - if (config_dir) i += 2; /* we will specify gaim's user dir */ - - ret = g_new(gchar *, i); - ret[j++] = g_strdup(myself); - - if (client_id) { - ret[j++] = g_strdup("--session"); - ret[j++] = g_strdup(client_id); - } - - if (config_dir) { - ret[j++] = g_strdup("--config"); - ret[j++] = g_strdup(config_dir); - } - - ret[j++] = NULL; - - return ret; -} - -/* SM callback handlers */ - -static void session_save_yourself(SmcConn conn, SmPointer data, int save_type, - Bool shutdown, int interact_style, Bool fast) { - if (had_first_save == FALSE && save_type == SmSaveLocal && - interact_style == SmInteractStyleNone && !shutdown && - !fast) { - /* this is just a dry run, spit it back */ - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Received first save_yourself\n"); - SmcSaveYourselfDone(conn, True); - had_first_save = TRUE; - return; - } - - /* tum ti tum... don't add anything else here without * - * reading SMlib.PS from an X.org ftp server near you */ - - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Received save_yourself\n"); - - if (save_type == SmSaveGlobal || save_type == SmSaveBoth) { - /* may as well do something ... */ - /* or not -- save_prefs(); */ - } - - SmcSaveYourselfDone(conn, True); -} - -static void session_die(SmcConn conn, SmPointer data) { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Received die\n"); - gaim_core_quit(); -} - -static void session_save_complete(SmcConn conn, SmPointer data) { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Received save_complete\n"); -} - -static void session_shutdown_cancelled(SmcConn conn, SmPointer data) { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Received shutdown_cancelled\n"); -} - -/* utility functions stolen from Gnome-client */ - -static void session_set_value(SmcConn conn, gchar *name, char *type, - int num_vals, SmPropValue *vals) { - SmProp *proplist[1]; - SmProp prop; - - g_return_if_fail(conn); - - prop.name = name; - prop.type = type; - prop.num_vals = num_vals; - prop.vals = vals; - - proplist[0] = ∝ - SmcSetProperties(conn, 1, proplist); -} - -static void session_set_string(SmcConn conn, gchar *name, gchar *value) { - SmPropValue val; - - g_return_if_fail(name); - - val.length = strlen (value)+1; - val.value = value; - - session_set_value(conn, name, SmARRAY8, 1, &val); -} - -static void session_set_gchar(SmcConn conn, gchar *name, gchar value) { - SmPropValue val; - - g_return_if_fail(name); - - val.length = 1; - val.value = &value; - - session_set_value(conn, name, SmCARD8, 1, &val); -} - -static void session_set_array(SmcConn conn, gchar *name, gchar *array[]) { - gint argc; - gchar **ptr; - gint i; - - SmPropValue *vals; - - g_return_if_fail (name); - - /* We count the number of elements in our array. */ - for (ptr = array, argc = 0; *ptr ; ptr++, argc++) /* LOOP */; - - /* Now initialize the 'vals' array. */ - vals = g_new (SmPropValue, argc); - for (ptr = array, i = 0 ; i < argc ; ptr++, i++) { - vals[i].length = strlen (*ptr); - vals[i].value = *ptr; - } - - session_set_value(conn, name, SmLISTofARRAY8, argc, vals); - - g_free (vals); -} - -#endif /* USE_SM */ - -/* setup functions */ - -void session_init(gchar *argv0, gchar *previous_id, gchar *config_dir) { -#ifdef USE_SM - SmcCallbacks callbacks; - gchar *client_id = NULL; - gchar error[ERROR_LENGTH] = ""; - gchar *tmp = NULL; - gchar **cmd = NULL; - - if (session != NULL) { - /* session is already established, what the hell is going on? */ - gaim_debug(GAIM_DEBUG_WARNING, "Session Management", - "Duplicated call to session_init!\n"); - return; - } - - if (g_getenv("SESSION_MANAGER") == NULL) { - gaim_debug(GAIM_DEBUG_ERROR, "Session Management", - "No SESSION_MANAGER found, aborting.\n"); - return; - } - - ice_init(); - - callbacks.save_yourself.callback = session_save_yourself; - callbacks.die.callback = session_die; - callbacks.save_complete.callback = session_save_complete; - callbacks.shutdown_cancelled.callback = session_shutdown_cancelled; - - callbacks.save_yourself.client_data = NULL; - callbacks.die.client_data = NULL; - callbacks.save_complete.client_data = NULL; - callbacks.shutdown_cancelled.client_data = NULL; - - if (previous_id) { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Connecting with previous ID %s\n", previous_id); - } else { - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Connecting with no previous ID\n"); - } - - session = SmcOpenConnection(NULL, "session", SmProtoMajor, SmProtoMinor, SmcSaveYourselfProcMask | - SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, - &callbacks, previous_id, &client_id, ERROR_LENGTH, error); - - if (session == NULL) { - if (error[0] != '\0') { - gaim_debug(GAIM_DEBUG_ERROR, "Session Management", - "Connection failed with error: %s\n", error); - } else { - gaim_debug(GAIM_DEBUG_ERROR, "Session Management", - "Connetion failed with unknown error.\n"); - } - return; - } - - tmp = SmcVendor(session); - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Connected to manager (%s) with client ID %s\n", - tmp, client_id); - g_free(tmp); - - session_managed = TRUE; - gdk_set_sm_client_id(client_id); - - tmp = g_get_current_dir(); - session_set_string(session, SmCurrentDirectory, tmp); - g_free(tmp); - - tmp = g_strdup_printf("%d", (int) getpid()); - session_set_string(session, SmProcessID, tmp); - g_free(tmp); - - tmp = g_strdup(g_get_user_name()); - session_set_string(session, SmUserID, tmp); - g_free(tmp); - - session_set_gchar(session, SmRestartStyleHint, (gchar) SmRestartIfRunning); - session_set_string(session, SmProgram, g_get_prgname()); - - myself = g_strdup(argv0); - gaim_debug(GAIM_DEBUG_MISC, "Session Management", - "Using %s as command\n", myself); - - cmd = session_make_command(NULL, config_dir); - session_set_array(session, SmCloneCommand, cmd); - g_strfreev(cmd); - - /* this is currently useless, but gnome-session warns 'the following applications will not - save their current status' bla bla if we don't have it and the user checks 'Save Session' - when they log out */ - cmd = g_new(gchar *, 2); - cmd[0] = g_strdup("/bin/true"); - cmd[1] = NULL; - session_set_array(session, SmDiscardCommand, cmd); - g_strfreev(cmd); - - cmd = session_make_command(client_id, config_dir); - session_set_array(session, SmRestartCommand, cmd); - g_strfreev(cmd); - - g_free(client_id); -#endif /* USE_SM */ -} - -void session_end() { -#ifdef USE_SM - if (session == NULL) /* no session to close */ - return; - - SmcCloseConnection(session, 0, NULL); - - gaim_debug(GAIM_DEBUG_INFO, "Session Management", - "Connection closed.\n"); -#endif /* USE_SM */ -}