Mercurial > pidgin.yaz
annotate src/session.c @ 6056:395116fdd270
[gaim-migrate @ 6506]
I'm reverting the patch to make f2 retroactively toggle timestamps because
it causes highlighting in the gtkimhtml window to act strangely when
timestamps are disabled. Cheung, if you think you can fix this please do,
but it seems like it's due to the incomplete nature of invisibility in
GtkTextViews.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Tue, 08 Jul 2003 01:28:42 +0000 |
parents | 059d95c67cda |
children | 16e384bb7fbf |
rev | line source |
---|---|
4158 | 1 /* |
2 * session management for Gaim | |
3 * | |
4 * Copyright (C) 2002, Robert McQueen <robot101@debian.org> but | |
5 * much code shamelessly cribbed from GsmClient (C) 2001 Havoc | |
6 * Pennington, which is in turn inspired by various other pieces | |
7 * of code including GnomeClient (C) 1998 Carsten Schaar, Tom | |
8 * Tromey, and twm session code (C) 1998 The Open Group. | |
9 * | |
10 * This program is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 * | |
24 */ | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5593
diff
changeset
|
25 #include "internal.h" |
4158 | 26 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5593
diff
changeset
|
27 #include "debug.h" |
4158 | 28 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5593
diff
changeset
|
29 /* XXX */ |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5593
diff
changeset
|
30 extern void do_quit(); |
4210 | 31 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5593
diff
changeset
|
32 extern char *opt_rcfile_arg; |
4158 | 33 |
34 #ifdef USE_SM | |
35 | |
36 #include <X11/ICE/ICElib.h> | |
37 #include <X11/SM/SMlib.h> | |
38 #include <unistd.h> | |
39 #include <fcntl.h> | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5593
diff
changeset
|
40 |
4158 | 41 #define ERROR_LENGTH 512 |
42 | |
43 static IceIOErrorHandler ice_installed_io_error_handler; | |
44 static SmcConn session = NULL; | |
45 static gchar *myself = NULL; | |
46 static gboolean had_first_save = FALSE; | |
47 gboolean session_managed = FALSE; | |
48 | |
49 /* ICE belt'n'braces stuff */ | |
50 | |
51 static gboolean ice_process_messages(GIOChannel *channel, GIOCondition condition, | |
52 gpointer data) { | |
53 IceConn connection = (IceConn)data; | |
54 IceProcessMessagesStatus status; | |
55 | |
56 /* please don't block... please! */ | |
57 status = IceProcessMessages(connection, NULL, NULL); | |
58 | |
59 if (status == IceProcessMessagesIOError) { | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
60 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
61 "ICE IO error, closing connection... "); |
4158 | 62 |
63 /* IO error, please disconnect */ | |
64 IceSetShutdownNegotiation(connection, False); | |
65 IceCloseConnection(connection); | |
66 | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
67 gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); |
4158 | 68 |
69 /* cancel the handler */ | |
70 return FALSE; | |
71 } | |
72 | |
73 /* live to see another day */ | |
74 return TRUE; | |
75 } | |
76 | |
77 static void ice_connection_watch(IceConn connection, IcePointer client_data, | |
78 Bool opening, IcePointer *watch_data) { | |
79 guint input_id; | |
80 | |
81 if (opening) { | |
82 GIOChannel *channel; | |
83 | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
84 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
85 "Handling new ICE connection... "); |
4158 | 86 |
87 /* ensure ICE connection is not passed to child processes */ | |
88 fcntl(IceConnectionNumber(connection), F_SETFD, FD_CLOEXEC); | |
89 | |
90 /* get glib to watch the connection for us */ | |
91 channel = g_io_channel_unix_new(IceConnectionNumber(connection)); | |
92 input_id = g_io_add_watch(channel, G_IO_IN | G_IO_ERR, | |
93 ice_process_messages, connection); | |
94 g_io_channel_unref(channel); | |
95 | |
96 /* store the input ID as a pointer for when it closes */ | |
97 *watch_data = (IcePointer)GUINT_TO_POINTER(input_id); | |
98 } else { | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
99 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
100 "Handling closed ICE connection... "); |
4158 | 101 |
102 /* get the input ID back and stop watching it */ | |
103 input_id = GPOINTER_TO_UINT((gpointer) *watch_data); | |
104 g_source_remove(input_id); | |
105 } | |
106 | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
107 gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); |
4158 | 108 } |
109 | |
110 /* We call any handler installed before (or after) ice_init but | |
111 * avoid calling the default libICE handler which does an exit(). | |
112 * | |
113 * This means we do nothing by default, which is probably correct, | |
114 * the connection will get closed by libICE | |
115 */ | |
116 | |
117 static void ice_io_error_handler(IceConn connection) { | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
118 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
119 "Handling ICE IO error... "); |
4158 | 120 |
121 if (ice_installed_io_error_handler) | |
122 (*ice_installed_io_error_handler)(connection); | |
123 | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
124 gaim_debug(GAIM_DEBUG_INFO, NULL, "done.\n"); |
4158 | 125 } |
126 | |
127 static void ice_init() { | |
128 IceIOErrorHandler default_handler; | |
129 | |
130 ice_installed_io_error_handler = IceSetIOErrorHandler(NULL); | |
131 default_handler = IceSetIOErrorHandler(ice_io_error_handler); | |
132 | |
133 if (ice_installed_io_error_handler == default_handler) | |
134 ice_installed_io_error_handler = NULL; | |
135 | |
136 IceAddConnectionWatch(ice_connection_watch, NULL); | |
137 | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
138 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
139 "ICE initialized.\n"); |
4158 | 140 } |
141 | |
4281 | 142 /* my magic utility function */ |
143 | |
144 static gchar **session_make_command(gchar *client_id) { | |
145 gint i = 2; | |
146 gint j = 0; | |
147 gchar **ret; | |
148 | |
149 if (client_id) i += 2; | |
150 if (opt_rcfile_arg) i += 2; | |
151 | |
152 ret = g_new(gchar *, i); | |
153 ret[j++] = g_strdup(myself); | |
154 | |
155 if (client_id) { | |
156 ret[j++] = g_strdup("--session"); | |
157 ret[j++] = g_strdup(client_id); | |
158 } | |
159 | |
160 if (opt_rcfile_arg) { | |
161 ret[j++] = g_strdup("--file"); | |
162 ret[j++] = g_strdup(opt_rcfile_arg); | |
163 } | |
164 | |
165 ret[j++] = NULL; | |
166 | |
167 return ret; | |
168 } | |
169 | |
4158 | 170 /* SM callback handlers */ |
171 | |
172 void session_save_yourself(SmcConn conn, SmPointer data, int save_type, | |
173 Bool shutdown, int interact_style, Bool fast) { | |
174 if (had_first_save == FALSE && save_type == SmSaveLocal && | |
175 interact_style == SmInteractStyleNone && !shutdown && | |
176 !fast) { | |
177 /* this is just a dry run, spit it back */ | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
178 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
179 "Received first save_yourself\n"); |
4158 | 180 SmcSaveYourselfDone(conn, True); |
181 had_first_save = TRUE; | |
182 return; | |
183 } | |
184 | |
185 /* tum ti tum... don't add anything else here without * | |
186 * reading SMlib.PS from an X.org ftp server near you */ | |
187 | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
188 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
189 "Received save_yourself\n"); |
4158 | 190 |
191 if (save_type == SmSaveGlobal || save_type == SmSaveBoth) { | |
192 /* may as well do something ... */ | |
5593
b07aa997ddd8
[gaim-migrate @ 5997]
Christian Hammond <chipx86@chipx86.com>
parents:
5211
diff
changeset
|
193 /* or not -- save_prefs(); */ |
4158 | 194 } |
195 | |
196 SmcSaveYourselfDone(conn, True); | |
197 } | |
198 | |
199 void session_die(SmcConn conn, SmPointer data) { | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
200 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
201 "Received die\n"); |
4158 | 202 do_quit(); |
203 } | |
204 | |
205 void session_save_complete(SmcConn conn, SmPointer data) { | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
206 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
207 "Received save_complete\n"); |
4158 | 208 } |
209 | |
210 void session_shutdown_cancelled(SmcConn conn, SmPointer data) { | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
211 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
212 "Received shutdown_cancelled\n"); |
4158 | 213 } |
214 | |
215 /* utility functions stolen from Gnome-client */ | |
216 | |
217 static void session_set_value(SmcConn conn, gchar *name, char *type, | |
218 int num_vals, SmPropValue *vals) { | |
219 SmProp *proplist[1]; | |
220 SmProp prop; | |
221 | |
222 g_return_if_fail(conn); | |
223 | |
224 prop.name = name; | |
225 prop.type = type; | |
226 prop.num_vals = num_vals; | |
227 prop.vals = vals; | |
228 | |
229 proplist[0] = ∝ | |
230 SmcSetProperties(conn, 1, proplist); | |
231 } | |
232 | |
233 static void session_set_string(SmcConn conn, gchar *name, gchar *value) { | |
234 SmPropValue val; | |
235 | |
236 g_return_if_fail(name); | |
237 | |
238 val.length = strlen (value)+1; | |
239 val.value = value; | |
240 | |
241 session_set_value(conn, name, SmARRAY8, 1, &val); | |
242 } | |
243 | |
244 static void session_set_gchar(SmcConn conn, gchar *name, gchar value) { | |
245 SmPropValue val; | |
246 | |
247 g_return_if_fail(name); | |
248 | |
249 val.length = 1; | |
250 val.value = &value; | |
251 | |
252 session_set_value(conn, name, SmCARD8, 1, &val); | |
253 } | |
254 | |
255 static void session_set_array(SmcConn conn, gchar *name, gchar *array[]) { | |
256 gint argc; | |
257 gchar **ptr; | |
258 gint i; | |
259 | |
260 SmPropValue *vals; | |
261 | |
262 g_return_if_fail (name); | |
263 | |
264 /* We count the number of elements in our array. */ | |
265 for (ptr = array, argc = 0; *ptr ; ptr++, argc++) /* LOOP */; | |
266 | |
267 /* Now initialize the 'vals' array. */ | |
268 vals = g_new (SmPropValue, argc); | |
269 for (ptr = array, i = 0 ; i < argc ; ptr++, i++) { | |
270 vals[i].length = strlen (*ptr); | |
271 vals[i].value = *ptr; | |
272 } | |
273 | |
274 session_set_value(conn, name, SmLISTofARRAY8, argc, vals); | |
275 | |
276 g_free (vals); | |
277 } | |
278 | |
279 #endif /* USE_SM */ | |
280 | |
281 /* setup functions */ | |
282 | |
283 void session_init(gchar *argv0, gchar *previous_id) { | |
284 #ifdef USE_SM | |
285 SmcCallbacks callbacks; | |
286 gchar *client_id = NULL; | |
287 gchar error[ERROR_LENGTH] = ""; | |
288 gchar *tmp = NULL; | |
4281 | 289 gchar **cmd = NULL; |
4158 | 290 |
291 if (session != NULL) { | |
292 /* session is already established, what the hell is going on? */ | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
293 gaim_debug(GAIM_DEBUG_WARNING, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
294 "Duplicated call to session_init!\n"); |
4158 | 295 return; |
296 } | |
297 | |
298 if (g_getenv("SESSION_MANAGER") == NULL) { | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
299 gaim_debug(GAIM_DEBUG_ERROR, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
300 "No SESSION_MANAGER found, aborting.\n"); |
4158 | 301 return; |
302 } | |
303 | |
304 ice_init(); | |
305 | |
306 callbacks.save_yourself.callback = session_save_yourself; | |
307 callbacks.die.callback = session_die; | |
308 callbacks.save_complete.callback = session_save_complete; | |
309 callbacks.shutdown_cancelled.callback = session_shutdown_cancelled; | |
310 | |
311 callbacks.save_yourself.client_data = NULL; | |
312 callbacks.die.client_data = NULL; | |
313 callbacks.save_complete.client_data = NULL; | |
314 callbacks.shutdown_cancelled.client_data = NULL; | |
315 | |
4544 | 316 if (previous_id) { |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
317 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
318 "Connecting with previous ID %s\n", previous_id); |
4544 | 319 } else { |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
320 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
321 "Connecting with no previous ID\n"); |
4544 | 322 } |
4158 | 323 |
324 session = SmcOpenConnection(NULL, "session", SmProtoMajor, SmProtoMinor, SmcSaveYourselfProcMask | | |
325 SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, | |
326 &callbacks, previous_id, &client_id, ERROR_LENGTH, error); | |
327 | |
328 if (session == NULL) { | |
329 if (error[0] != '\0') { | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
330 gaim_debug(GAIM_DEBUG_ERROR, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
331 "Connection failed with error: %s\n", error); |
4158 | 332 } else { |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
333 gaim_debug(GAIM_DEBUG_ERROR, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
334 "Connetion failed with unknown error.\n"); |
4158 | 335 } |
336 return; | |
337 } | |
338 | |
339 tmp = SmcVendor(session); | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
340 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
341 "Connected to manager (%s) with client ID %s\n", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
342 tmp, client_id); |
4158 | 343 g_free(tmp); |
344 | |
345 session_managed = TRUE; | |
346 gdk_set_sm_client_id(client_id); | |
347 | |
4265 | 348 tmp = g_get_current_dir(); |
349 session_set_string(session, SmCurrentDirectory, tmp); | |
350 g_free(tmp); | |
351 | |
4210 | 352 tmp = g_strdup_printf("%d", (int) getpid()); |
4158 | 353 session_set_string(session, SmProcessID, tmp); |
354 g_free(tmp); | |
355 | |
4210 | 356 tmp = g_strdup(g_get_user_name()); |
4158 | 357 session_set_string(session, SmUserID, tmp); |
358 g_free(tmp); | |
359 | |
360 session_set_gchar(session, SmRestartStyleHint, (gchar) SmRestartIfRunning); | |
361 session_set_string(session, SmProgram, g_get_prgname()); | |
362 | |
363 myself = g_strdup(argv0); | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
364 gaim_debug(GAIM_DEBUG_MISC, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
365 "Using %s as command\n", myself); |
4158 | 366 |
4281 | 367 cmd = session_make_command(NULL); |
4158 | 368 session_set_array(session, SmCloneCommand, cmd); |
4281 | 369 g_strfreev(cmd); |
4158 | 370 |
4265 | 371 /* this is currently useless, but gnome-session warns 'the following applications will not |
372 save their current status' bla bla if we don't have it and the user checks 'Save Session' | |
373 when they log out */ | |
4281 | 374 cmd = g_new(gchar *, 2); |
375 cmd[0] = g_strdup("/bin/true"); | |
376 cmd[1] = NULL; | |
4158 | 377 session_set_array(session, SmDiscardCommand, cmd); |
4281 | 378 g_strfreev(cmd); |
4158 | 379 |
4281 | 380 cmd = session_make_command(client_id); |
4158 | 381 session_set_array(session, SmRestartCommand, cmd); |
4281 | 382 g_strfreev(cmd); |
383 | |
4158 | 384 g_free(client_id); |
385 #endif /* USE_SM */ | |
386 } | |
387 | |
388 void session_end() { | |
389 #ifdef USE_SM | |
390 if (session == NULL) /* no session to close */ | |
391 return; | |
392 | |
393 SmcCloseConnection(session, 0, NULL); | |
394 | |
5211
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
395 gaim_debug(GAIM_DEBUG_INFO, "Session Management", |
0241d6b6702d
[gaim-migrate @ 5581]
Christian Hammond <chipx86@chipx86.com>
parents:
4544
diff
changeset
|
396 "Connection closed.\n"); |
4158 | 397 #endif /* USE_SM */ |
398 } |