Mercurial > pidgin.yaz
annotate src/main.c @ 4571:51e988d015ed
[gaim-migrate @ 4852]
I don't know if this is gtk's problem or my (our?) misunderstanding of
GtkNotebook, but it seems pages that are deleted aren't destroying the
child widgets, so we're doing that manually now. It should free up a LOT
of memory, and since this is how the old code did it (I think), it should
explain the large memory leaks people used to report.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Tue, 11 Feb 2003 17:26:16 +0000 |
parents | 9df99116840a |
children | 4b1e24835bbf |
rev | line source |
---|---|
4489 | 1 /* |
2 * gaim | |
3 * | |
4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
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 of the License, or | |
9 * (at your option) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 | |
22 #ifdef HAVE_CONFIG_H | |
23 #include <config.h> | |
24 #endif | |
25 #ifdef GAIM_PLUGINS | |
26 #ifndef _WIN32 | |
27 #include <dlfcn.h> | |
28 #endif | |
29 #endif /* GAIM_PLUGINS */ | |
30 #include <gtk/gtk.h> | |
31 #ifndef _WIN32 | |
32 #include <gdk/gdkx.h> | |
33 #include <unistd.h> | |
34 #include <sys/socket.h> | |
35 #include <netinet/in.h> | |
36 #include <arpa/inet.h> | |
37 #include <sys/un.h> | |
38 #include <sys/wait.h> | |
39 #endif /* !_WIN32 */ | |
40 #include <gdk/gdk.h> | |
41 #include <sys/types.h> | |
42 #include <sys/stat.h> | |
43 #include <errno.h> | |
44 #include <stdio.h> | |
45 #include <string.h> | |
46 #include <stdarg.h> | |
47 #include <stdlib.h> | |
48 #include <ctype.h> | |
49 #include "prpl.h" | |
4561 | 50 #include "sound.h" |
4489 | 51 #include "gaim.h" |
52 #include "gaim-socket.h" | |
53 #if HAVE_SIGNAL_H | |
54 #include <signal.h> | |
55 #endif | |
56 #include "locale.h" | |
57 #include <getopt.h> | |
58 | |
59 #ifdef _WIN32 | |
60 #include "win32dep.h" | |
61 #endif | |
62 | |
63 static GtkWidget *name; | |
64 static GtkWidget *pass; | |
65 | |
66 GList *log_conversations = NULL; | |
67 GList *buddy_pounces = NULL; | |
68 GSList *away_messages = NULL; | |
69 GSList *message_queue = NULL; | |
70 GSList *unread_message_queue = NULL; | |
71 GSList *away_time_queue = NULL; | |
72 | |
73 GtkWidget *mainwindow = NULL; | |
74 | |
4561 | 75 |
4489 | 76 int opt_away = 0; |
77 char *opt_away_arg = NULL; | |
78 char *opt_rcfile_arg = NULL; | |
79 int opt_debug = 0; | |
80 #ifdef _WIN32 | |
81 int opt_gdebug = 0; | |
82 #endif | |
83 | |
84 #if HAVE_SIGNAL_H | |
85 /* | |
86 * Lists of signals we wish to catch and those we wish to ignore. | |
87 * Each list terminated with -1 | |
88 */ | |
89 static int catch_sig_list[] = { | |
90 SIGSEGV, | |
91 SIGHUP, | |
92 SIGINT, | |
93 SIGTERM, | |
94 SIGQUIT, | |
95 SIGCHLD, | |
96 -1 | |
97 }; | |
98 | |
99 static int ignore_sig_list[] = { | |
100 SIGPIPE, | |
101 -1 | |
102 }; | |
103 #endif | |
104 | |
105 void do_quit() | |
106 { | |
107 /* captain's log, stardate... */ | |
108 system_log(log_quit, NULL, NULL, OPT_LOG_BUDDY_SIGNON | OPT_LOG_MY_SIGNON); | |
109 | |
110 /* the self destruct sequence has been initiated */ | |
111 plugin_event(event_quit); | |
112 | |
113 /* transmission ends */ | |
114 signoff_all(); | |
115 | |
116 /* record what we have before we blow it away... */ | |
117 save_prefs(); | |
118 | |
119 #ifdef GAIM_PLUGINS | |
120 /* jettison cargo */ | |
121 remove_all_plugins(); | |
122 #endif | |
123 | |
124 #ifdef USE_PERL | |
125 /* yup, perl too */ | |
126 perl_end(); | |
127 #endif | |
128 | |
129 #ifdef USE_SM | |
130 /* unplug */ | |
131 session_end(); | |
132 #endif | |
133 | |
134 /* and end it all... */ | |
135 gtk_main_quit(); | |
136 } | |
137 | |
4561 | 138 static guint snd_tmout = 0; |
4489 | 139 static gboolean sound_timeout(gpointer data) |
140 { | |
4561 | 141 gaim_sound_set_login_mute(FALSE); |
142 snd_tmout = 0; | |
4489 | 143 return FALSE; |
144 } | |
145 | |
146 /* we need to do this for Oscar because serv_login only starts the login | |
147 * process, it doesn't end there. gaim_setup will be called later from | |
148 * oscar.c, after the buddy list is made and serv_finish_login is called */ | |
149 void gaim_setup(struct gaim_connection *gc) | |
150 { | |
151 if ((sound_options & OPT_SOUND_LOGIN) && (sound_options & OPT_SOUND_SILENT_SIGNON)) { | |
4561 | 152 if(snd_tmout) { |
153 g_source_remove(snd_tmout); | |
154 } | |
155 gaim_sound_set_login_mute(TRUE); | |
4489 | 156 snd_tmout = g_timeout_add(10000, sound_timeout, NULL); |
157 } | |
158 } | |
159 | |
160 static gboolean domiddleclick(GtkWidget *w, GdkEventButton *event, gpointer null) | |
161 { | |
162 if (event->button != 2) | |
163 return FALSE; | |
164 | |
165 auto_login(); | |
166 return TRUE; | |
167 } | |
168 | |
169 static void dologin(GtkWidget *widget, GtkWidget *w) | |
170 { | |
4491 | 171 struct gaim_account *account; |
4489 | 172 const char *username = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(name)->entry)); |
173 const char *password = gtk_entry_get_text(GTK_ENTRY(pass)); | |
174 | |
175 if (!strlen(username)) { | |
176 do_error_dialog(_("Please enter your login."), NULL, GAIM_ERROR); | |
177 return; | |
178 } | |
179 | |
180 /* if there is more than one user of the same name, then fuck | |
181 * them, they just have to use the account editor to sign in | |
182 * the second one */ | |
183 | |
4491 | 184 account = gaim_account_find(username, -1); |
185 if (!account) | |
186 account = gaim_account_new(username, DEFAULT_PROTO, OPT_ACCT_REM_PASS); | |
187 g_snprintf(account->password, sizeof account->password, "%s", password); | |
4489 | 188 save_prefs(); |
4491 | 189 serv_login(account); |
4489 | 190 } |
191 | |
192 /* <name> is a comma-separated list of names, or NULL | |
193 if NULL and there is at least one user defined in .gaimrc, try to login. | |
194 if not NULL, parse <name> into separate strings, look up each one in | |
195 .gaimrc and, if it's there, try to login. | |
196 returns: 0 if successful | |
197 -1 if no user was found that had a saved password | |
198 */ | |
199 static int dologin_named(char *name) | |
200 { | |
4491 | 201 struct gaim_account *account; |
4489 | 202 char **names, **n; |
203 int retval = -1; | |
204 | |
205 if (name !=NULL) { /* list of names given */ | |
206 names = g_strsplit(name, ",", 32); | |
207 for (n = names; *n != NULL; n++) { | |
4491 | 208 account = gaim_account_find(*n, -1); |
209 if (account) { /* found a user */ | |
210 if (account->options & OPT_ACCT_REM_PASS) { | |
4489 | 211 retval = 0; |
4491 | 212 serv_login(account); |
4489 | 213 } |
214 } | |
215 } | |
216 g_strfreev(names); | |
217 } else { /* no name given, use default */ | |
4491 | 218 account = (struct gaim_account *)gaim_accounts->data; |
219 if (account->options & OPT_ACCT_REM_PASS) { | |
4489 | 220 retval = 0; |
4491 | 221 serv_login(account); |
4489 | 222 } |
223 } | |
224 | |
225 return retval; | |
226 } | |
227 | |
228 | |
229 static void doenter(GtkWidget *widget, GtkWidget *w) | |
230 { | |
231 if (widget == name) { | |
232 gtk_entry_set_text(GTK_ENTRY(pass), ""); | |
233 gtk_entry_select_region(GTK_ENTRY(GTK_COMBO(name)->entry), 0, 0); | |
234 gtk_widget_grab_focus(pass); | |
235 } else if (widget == pass) { | |
236 dologin(widget, w); | |
237 } | |
238 } | |
239 | |
240 | |
241 static void combo_changed(GtkWidget *w, GtkWidget *combo) | |
242 { | |
243 const char *txt = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); | |
4491 | 244 struct gaim_account *account; |
4489 | 245 |
4491 | 246 account = gaim_account_find(txt, -1); |
4489 | 247 |
4491 | 248 if (account && account->options & OPT_ACCT_REM_PASS) { |
249 gtk_entry_set_text(GTK_ENTRY(pass), account->password); | |
4489 | 250 } else { |
251 gtk_entry_set_text(GTK_ENTRY(pass), ""); | |
252 } | |
253 } | |
254 | |
255 | |
256 static GList *combo_user_names() | |
257 { | |
4491 | 258 GSList *accts = gaim_accounts; |
4489 | 259 GList *tmp = NULL; |
4491 | 260 struct gaim_account *account; |
4489 | 261 |
4491 | 262 if (!accts) |
4489 | 263 return g_list_append(NULL, _("<New User>")); |
264 | |
4491 | 265 while (accts) { |
266 account = (struct gaim_account *)accts->data; | |
267 tmp = g_list_append(tmp, account->username); | |
268 accts = accts->next; | |
4489 | 269 } |
270 | |
271 return tmp; | |
272 } | |
273 | |
274 static void login_window_closed(GtkWidget *w, GdkEvent *ev, gpointer d) | |
275 { | |
276 if(docklet_count) { | |
277 #if _WIN32 | |
278 wgaim_systray_minimize(mainwindow); | |
279 #endif | |
280 gtk_widget_hide(mainwindow); | |
281 } else | |
282 do_quit(); | |
283 } | |
284 | |
285 void show_login() | |
286 { | |
287 GdkPixbuf *icon; | |
288 GtkWidget *image; | |
289 GtkWidget *vbox; | |
290 GtkWidget *button; | |
291 GtkWidget *hbox; | |
292 GtkWidget *label; | |
293 GtkWidget *vbox2; | |
294 GList *tmp; | |
295 | |
296 /* Do we already have a main window opened? If so, bring it back, baby... ribs... yeah */ | |
297 if (mainwindow) { | |
298 gtk_window_present(GTK_WINDOW(mainwindow)); | |
299 return; | |
300 } | |
301 | |
302 mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
303 | |
304 gtk_window_set_role(GTK_WINDOW(mainwindow), "login"); | |
305 gtk_window_set_policy(GTK_WINDOW(mainwindow), FALSE, FALSE, TRUE); | |
306 gtk_window_set_title(GTK_WINDOW(mainwindow), _("Gaim - Login")); | |
307 gtk_widget_realize(mainwindow); | |
308 gdk_window_set_group(mainwindow->window, mainwindow->window); | |
309 gtk_container_set_border_width(GTK_CONTAINER(mainwindow), 5); | |
310 g_signal_connect(G_OBJECT(mainwindow), "delete_event", | |
311 G_CALLBACK(login_window_closed), mainwindow); | |
312 | |
313 | |
314 icon = gaim_pixbuf(NULL, "gaim.png"); | |
315 if (icon) { | |
316 gtk_window_set_icon(GTK_WINDOW(mainwindow), icon); | |
317 gdk_pixbuf_unref(icon); | |
318 } | |
319 | |
320 vbox = gtk_vbox_new(FALSE, 0); | |
321 gtk_container_add(GTK_CONTAINER(mainwindow), vbox); | |
322 | |
323 image = gaim_pixmap(NULL, "logo.png"); | |
324 gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0); | |
325 | |
326 vbox2 = gtk_vbox_new(FALSE, 0); | |
327 gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); | |
328 | |
329 label = gtk_label_new(_("Screen Name:")); | |
330 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
331 gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0); | |
332 | |
333 name = gtk_combo_new(); | |
334 tmp = combo_user_names(); | |
335 gtk_combo_set_popdown_strings(GTK_COMBO(name), tmp); | |
336 g_list_free(tmp); | |
337 g_signal_connect(G_OBJECT(GTK_COMBO(name)->entry), "activate", | |
338 G_CALLBACK(doenter), mainwindow); | |
339 g_signal_connect(G_OBJECT(GTK_COMBO(name)->entry), "changed", | |
340 G_CALLBACK(combo_changed), name); | |
341 gtk_box_pack_start(GTK_BOX(vbox2), name, FALSE, TRUE, 0); | |
342 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, TRUE, 0); | |
343 | |
344 vbox2 = gtk_vbox_new(FALSE, 0); | |
345 gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); | |
346 | |
347 label = gtk_label_new(_("Password:")); | |
348 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
349 gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0); | |
350 | |
351 pass = gtk_entry_new(); | |
352 gtk_entry_set_visibility(GTK_ENTRY(pass), FALSE); | |
353 g_signal_connect(G_OBJECT(pass), "activate", | |
354 G_CALLBACK(doenter), mainwindow); | |
355 gtk_box_pack_start(GTK_BOX(vbox2), pass, FALSE, TRUE, 0); | |
356 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, TRUE, 0); | |
357 | |
358 /* Now for the button box */ | |
359 hbox = gtk_hbox_new(TRUE, 0); | |
360 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 5); | |
361 | |
362 /* And now for the buttons */ | |
363 button = gaim_pixbuf_button("Accounts", "accounts.png", GAIM_BUTTON_VERTICAL); | |
364 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
365 g_signal_connect(G_OBJECT(button), "clicked", | |
366 G_CALLBACK(account_editor), mainwindow); | |
367 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
368 | |
369 #ifdef NO_MULTI | |
370 gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); | |
371 #endif | |
372 | |
373 button = gaim_pixbuf_button("Settings", "preferences.png", GAIM_BUTTON_VERTICAL); | |
374 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
375 g_signal_connect(G_OBJECT(button), "clicked", | |
376 G_CALLBACK(show_prefs), mainwindow); | |
377 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
378 | |
379 button = gaim_pixbuf_button("Sign On", "signon.png", GAIM_BUTTON_VERTICAL); | |
380 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); | |
381 g_signal_connect(G_OBJECT(button), "clicked", | |
382 G_CALLBACK(dologin), mainwindow); | |
383 g_signal_connect(G_OBJECT(button), "button-press-event", G_CALLBACK(domiddleclick), NULL); | |
384 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
385 | |
386 #ifdef _WIN32 | |
387 /* Register newly created window with systray module */ | |
388 wgaim_created_loginwin(GTK_WIDGET(mainwindow)); | |
389 #endif | |
390 | |
391 /* Now grab the focus that we need */ | |
4491 | 392 if (gaim_accounts) { |
393 struct gaim_account *account = gaim_accounts->data; | |
394 if (account->options & OPT_ACCT_REM_PASS) { | |
4489 | 395 combo_changed(NULL, name); |
396 gtk_widget_grab_focus(button); | |
397 } else { | |
398 gtk_widget_grab_focus(pass); | |
399 } | |
400 } else { | |
401 gtk_widget_grab_focus(name); | |
402 } | |
403 | |
404 /* And raise the curtain! */ | |
405 gtk_widget_show_all(mainwindow); | |
406 | |
407 } | |
408 | |
409 #if HAVE_SIGNAL_H | |
410 void sighandler(int sig) | |
411 { | |
412 switch (sig) { | |
413 case SIGHUP: | |
414 debug_printf("caught signal %d\n", sig); | |
415 signoff_all(NULL, NULL); | |
416 break; | |
417 case SIGSEGV: | |
418 core_quit(); | |
419 #ifndef DEBUG | |
420 fprintf(stderr, "Gaim has segfaulted and attempted to dump a core file.\n" | |
421 "This is a bug in the software and has happened through\n" | |
422 "no fault of your own.\n\n" | |
423 "It is possible that this bug is already fixed in CVS.\n" | |
424 "You can get a tarball of CVS from the Gaim website, at\n" | |
425 WEBSITE "gaim-CVS.tar.gz.\n\n" | |
426 "If you are already using CVS, or can reproduce the crash\n" | |
427 "using the CVS version, please notify the gaim maintainers\n" | |
428 "by reporting a bug at\n" | |
429 WEBSITE "bug.php\n\n" | |
430 "Please make sure to specify what you were doing at the time,\n" | |
431 "and post the backtrace from the core file. If you do not know\n" | |
432 "how to get the backtrace, please get instructions at\n" | |
433 WEBSITE "gdb.php. If you need further\n" | |
434 "assistance, please IM either RobFlynn or SeanEgn and\n" | |
435 "they can help you.\n"); | |
436 #else | |
437 fprintf(stderr, "Oh no! Segmentation fault!\n"); | |
438 g_on_error_query (g_get_prgname()); | |
439 exit(1); | |
440 #endif | |
441 abort(); | |
442 break; | |
443 case SIGCHLD: | |
444 clean_pid(); | |
445 #if HAVE_SIGNAL_H | |
446 signal(SIGCHLD, sighandler); /* restore signal catching on this one! */ | |
447 #endif | |
448 break; | |
449 default: | |
450 debug_printf("caught signal %d\n", sig); | |
451 signoff_all(NULL, NULL); | |
452 #ifdef GAIM_PLUGINS | |
453 remove_all_plugins(); | |
454 #endif | |
455 if (gtk_main_level()) | |
456 gtk_main_quit(); | |
457 core_quit(); | |
458 exit(0); | |
459 } | |
460 } | |
461 #endif | |
462 | |
463 #ifndef _WIN32 | |
464 static gboolean socket_readable(GIOChannel *source, GIOCondition cond, gpointer ud) | |
465 { | |
466 guchar type; | |
467 guchar subtype; | |
468 guint32 len; | |
469 guchar *data; | |
470 guint32 x; | |
471 | |
472 debug_printf("Core says: "); | |
473 g_io_channel_read(source, &type, sizeof(type), &x); | |
474 if (x == 0) { | |
475 debug_printf("CORE IS GONE!\n"); | |
476 g_io_channel_close(source); | |
477 return FALSE; | |
478 } | |
479 debug_printf("%d ", type); | |
480 g_io_channel_read(source, &subtype, sizeof(subtype), &x); | |
481 if (x == 0) { | |
482 debug_printf("CORE IS GONE!\n"); | |
483 g_io_channel_close(source); | |
484 return FALSE; | |
485 } | |
486 debug_printf("%d ", subtype); | |
487 g_io_channel_read(source, (guchar *)&len, sizeof(len), &x); | |
488 if (x == 0) { | |
489 debug_printf("CORE IS GONE!\n"); | |
490 g_io_channel_close(source); | |
491 return FALSE; | |
492 } | |
493 debug_printf("(%d bytes)\n", len); | |
494 | |
495 data = g_malloc(len); | |
496 g_io_channel_read(source, data, len, &x); | |
497 if (x != len) { | |
498 debug_printf("CORE IS GONE! (read %d/%d bytes)\n", x, len); | |
499 g_free(data); | |
500 g_io_channel_close(source); | |
501 return FALSE; | |
502 } | |
503 | |
504 g_free(data); | |
505 return TRUE; | |
506 } | |
507 #endif /* _WIN32 */ | |
508 | |
509 static int ui_main() | |
510 { | |
511 #ifndef _WIN32 | |
512 GIOChannel *channel; | |
513 int UI_fd; | |
514 char name[256]; | |
515 GList *icons = NULL; | |
516 GdkPixbuf *icon = NULL; | |
517 char *icon_path; | |
518 #endif | |
519 if (current_smiley_theme == NULL) { | |
520 smiley_theme_probe(); | |
521 if (smiley_themes) { | |
522 struct smiley_theme *smile = smiley_themes->data; | |
523 load_smiley_theme(smile->path, TRUE); | |
524 } | |
525 } | |
526 | |
4514
7521e29658bc
[gaim-migrate @ 4792]
Christian Hammond <chipx86@chipx86.com>
parents:
4491
diff
changeset
|
527 /* Set the UI operation structures. */ |
4489 | 528 gaim_set_win_ui_ops(gaim_get_gtk_window_ui_ops()); |
4514
7521e29658bc
[gaim-migrate @ 4792]
Christian Hammond <chipx86@chipx86.com>
parents:
4491
diff
changeset
|
529 gaim_set_xfer_ui_ops(gaim_get_gtk_xfer_ui_ops()); |
4489 | 530 |
531 setup_stock(); | |
532 | |
4561 | 533 gaim_sound_init(); |
534 | |
4489 | 535 #ifndef _WIN32 |
536 /* use the nice PNG icon for all the windows */ | |
537 icon_path = g_build_filename(DATADIR, "pixmaps", "gaim.png", NULL); | |
538 icon = gdk_pixbuf_new_from_file(icon_path, NULL); | |
539 g_free(icon_path); | |
540 if (icon) { | |
541 icons = g_list_append(icons,icon); | |
542 gtk_window_set_default_icon_list(icons); | |
543 g_object_unref(G_OBJECT(icon)); | |
544 } else { | |
545 debug_printf("Failed to load icon from %s" G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S "gaim.png\n",DATADIR); | |
546 } | |
547 | |
548 g_snprintf(name, sizeof(name), "%s" G_DIR_SEPARATOR_S "gaim_%s.%d", g_get_tmp_dir(), g_get_user_name(), gaim_session); | |
549 UI_fd = gaim_connect_to_session(0); | |
550 if (UI_fd < 0) | |
551 return 1; | |
552 | |
553 channel = g_io_channel_unix_new(UI_fd); | |
554 g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR, socket_readable, NULL); | |
555 #endif | |
556 return 0; | |
557 } | |
558 | |
559 static void set_first_user(char *name) | |
560 { | |
4491 | 561 struct gaim_account *account; |
4489 | 562 |
4491 | 563 account = gaim_account_find(name, -1); |
4489 | 564 |
4491 | 565 if (!account) { /* new user */ |
566 account = g_new0(struct gaim_account, 1); | |
567 g_snprintf(account->username, sizeof(account->username), "%s", name); | |
568 account->protocol = DEFAULT_PROTO; | |
569 gaim_accounts = g_slist_prepend(gaim_accounts, account); | |
4489 | 570 } else { /* user already exists */ |
4491 | 571 gaim_accounts = g_slist_remove(gaim_accounts, account); |
572 gaim_accounts = g_slist_prepend(gaim_accounts, account); | |
4489 | 573 } |
574 save_prefs(); | |
575 } | |
576 | |
577 #ifdef _WIN32 | |
578 /* WIN32 print and log handlers */ | |
579 | |
580 static void gaim_dummy_print( const gchar* string ) { | |
581 return; | |
582 } | |
583 | |
584 static void gaim_dummy_log_handler (const gchar *domain, | |
585 GLogLevelFlags flags, | |
586 const gchar *msg, | |
587 gpointer user_data) { | |
588 return; | |
589 } | |
590 | |
591 static void gaim_log_handler (const gchar *domain, | |
592 GLogLevelFlags flags, | |
593 const gchar *msg, | |
594 gpointer user_data) { | |
595 debug_printf("%s - %s\n", domain, msg); | |
596 g_log_default_handler(domain, flags, msg, user_data); | |
597 } | |
598 #endif /* _WIN32 */ | |
599 | |
600 /* FUCKING GET ME A TOWEL! */ | |
601 #ifdef _WIN32 | |
602 int gaim_main(int argc, char *argv[]) | |
603 #else | |
604 int main(int argc, char *argv[]) | |
605 #endif | |
606 { | |
607 int opt_acct = 0, opt_help = 0, opt_version = 0, opt_login = 0, opt_nologin = 0, dologin_ret = -1; | |
608 char *opt_user_arg = NULL, *opt_login_arg = NULL; | |
609 char *opt_session_arg = NULL; | |
610 #if HAVE_SIGNAL_H | |
611 int sig_indx; /* for setting up signal catching */ | |
612 sigset_t sigset; | |
613 void (*prev_sig_disp)(); | |
614 #endif | |
615 int opt, opt_user = 0; | |
616 int i; | |
617 | |
618 struct option long_options[] = { | |
619 {"acct", no_argument, NULL, 'a'}, | |
620 /*{"away", optional_argument, NULL, 'w'}, */ | |
621 {"help", no_argument, NULL, 'h'}, | |
622 /*{"login", optional_argument, NULL, 'l'}, */ | |
623 {"loginwin", no_argument, NULL, 'n'}, | |
624 {"user", required_argument, NULL, 'u'}, | |
625 {"file", required_argument, NULL, 'f'}, | |
626 {"debug", no_argument, NULL, 'd'}, | |
627 {"version", no_argument, NULL, 'v'}, | |
628 {"session", required_argument, NULL, 's'}, | |
629 {0, 0, 0, 0} | |
630 }; | |
631 | |
632 #ifdef DEBUG | |
633 opt_debug = 1; | |
634 #endif | |
635 | |
636 #ifdef ENABLE_NLS | |
637 bindtextdomain(PACKAGE, LOCALEDIR); | |
638 bind_textdomain_codeset(PACKAGE, "UTF-8"); | |
639 textdomain(PACKAGE); | |
640 #endif | |
641 | |
642 #if HAVE_SIGNAL_H | |
643 /* Let's not violate any PLA's!!!! */ | |
644 /* jseymour: whatever the fsck that means */ | |
645 /* Robot101: for some reason things like gdm like to block * | |
646 * useful signals like SIGCHLD, so we unblock all the ones we * | |
647 * declare a handler for. thanks JSeymour and Vann. */ | |
648 if (sigemptyset(&sigset)) { | |
649 char errmsg[BUFSIZ]; | |
650 sprintf(errmsg, "Warning: couldn't initialise empty signal set"); | |
651 perror(errmsg); | |
652 } | |
653 for(sig_indx = 0; catch_sig_list[sig_indx] != -1; ++sig_indx) { | |
654 if((prev_sig_disp = signal(catch_sig_list[sig_indx], sighandler)) == SIG_ERR) { | |
655 char errmsg[BUFSIZ]; | |
656 sprintf(errmsg, "Warning: couldn't set signal %d for catching", | |
657 catch_sig_list[sig_indx]); | |
658 perror(errmsg); | |
659 } | |
660 if(sigaddset(&sigset, catch_sig_list[sig_indx])) { | |
661 char errmsg[BUFSIZ]; | |
662 sprintf(errmsg, "Warning: couldn't include signal %d for unblocking", | |
663 catch_sig_list[sig_indx]); | |
664 perror(errmsg); | |
665 } | |
666 } | |
667 for(sig_indx = 0; ignore_sig_list[sig_indx] != -1; ++sig_indx) { | |
668 if((prev_sig_disp = signal(ignore_sig_list[sig_indx], SIG_IGN)) == SIG_ERR) { | |
669 char errmsg[BUFSIZ]; | |
670 sprintf(errmsg, "Warning: couldn't set signal %d to ignore", | |
671 ignore_sig_list[sig_indx]); | |
672 perror(errmsg); | |
673 } | |
674 } | |
675 | |
676 if (sigprocmask(SIG_UNBLOCK, &sigset, NULL)) { | |
677 char errmsg[BUFSIZ]; | |
678 sprintf(errmsg, "Warning: couldn't unblock signals"); | |
679 perror(errmsg); | |
680 } | |
681 #endif | |
682 | |
683 for (i = 0; i < argc; i++) { | |
684 /* --login option */ | |
685 if (strstr(argv[i], "--l") == argv[i]) { | |
686 char *equals; | |
687 opt_login = 1; | |
688 if ((equals = strchr(argv[i], '=')) != NULL) { | |
689 /* --login=NAME */ | |
690 opt_login_arg = g_strdup(equals + 1); | |
691 if (strlen(opt_login_arg) == 0) { | |
692 g_free(opt_login_arg); | |
693 opt_login_arg = NULL; | |
694 } | |
695 } else if (i + 1 < argc && argv[i + 1][0] != '-') { | |
696 /* --login NAME */ | |
697 opt_login_arg = g_strdup(argv[i + 1]); | |
698 strcpy(argv[i + 1], " "); | |
699 } | |
700 strcpy(argv[i], " "); | |
701 } | |
702 /* -l option */ | |
703 else if (strstr(argv[i], "-l") == argv[i]) { | |
704 opt_login = 1; | |
705 if (strlen(argv[i]) > 2) { | |
706 /* -lNAME */ | |
707 opt_login_arg = g_strdup(argv[i] + 2); | |
708 } else if (i + 1 < argc && argv[i + 1][0] != '-') { | |
709 /* -l NAME */ | |
710 opt_login_arg = g_strdup(argv[i + 1]); | |
711 strcpy(argv[i + 1], " "); | |
712 } | |
713 strcpy(argv[i], " "); | |
714 } | |
715 /* --away option */ | |
716 else if (strstr(argv[i], "--aw") == argv[i]) { | |
717 char *equals; | |
718 opt_away = 1; | |
719 if ((equals = strchr(argv[i], '=')) != NULL) { | |
720 /* --away=MESG */ | |
721 opt_away_arg = g_strdup(equals + 1); | |
722 if (strlen(opt_away_arg) == 0) { | |
723 g_free(opt_away_arg); | |
724 opt_away_arg = NULL; | |
725 } | |
726 } else if (i + 1 < argc && argv[i + 1][0] != '-') { | |
727 /* --away MESG */ | |
728 opt_away_arg = g_strdup(argv[i + 1]); | |
729 strcpy(argv[i + 1], " "); | |
730 } | |
731 strcpy(argv[i], " "); | |
732 } | |
733 /* -w option */ | |
734 else if (strstr(argv[i], "-w") == argv[i]) { | |
735 opt_away = 1; | |
736 if (strlen(argv[i]) > 2) { | |
737 /* -wMESG */ | |
738 opt_away_arg = g_strdup(argv[i] + 2); | |
739 } else if (i + 1 < argc && argv[i + 1][0] != '-') { | |
740 /* -w MESG */ | |
741 opt_away_arg = g_strdup(argv[i + 1]); | |
742 strcpy(argv[i + 1], " "); | |
743 } | |
744 strcpy(argv[i], " "); | |
745 } | |
746 } | |
747 /* | |
748 if (opt_login) { | |
749 printf ("--login given with arg %s\n", | |
750 opt_login_arg ? opt_login_arg : "NULL"); | |
751 exit(0); | |
752 } | |
753 */ | |
754 | |
755 gtk_set_locale(); | |
756 gtk_init(&argc, &argv); | |
757 | |
758 /* scan command-line options */ | |
759 opterr = 1; | |
760 while ((opt = getopt_long(argc, argv, | |
761 #ifndef _WIN32 | |
762 "adhu:f:vns:", | |
763 #else | |
764 "adghu:f:vn", | |
765 #endif | |
766 long_options, NULL)) != -1) { | |
767 switch (opt) { | |
768 case 'u': /* set user */ | |
769 opt_user = 1; | |
770 opt_user_arg = g_strdup(optarg); | |
771 break; | |
772 case 'a': /* account editor */ | |
773 opt_acct = 1; | |
774 break; | |
775 case 'd': /* debug */ | |
776 opt_debug = 1; | |
777 break; | |
778 case 'f': | |
779 opt_rcfile_arg = g_strdup(optarg); | |
780 break; | |
781 case 's': /* use existing session ID */ | |
782 opt_session_arg = g_strdup(optarg); | |
783 break; | |
784 case 'v': /* version */ | |
785 opt_version = 1; | |
786 break; | |
787 case 'h': /* help */ | |
788 opt_help = 1; | |
789 break; | |
790 case 'n': /* don't autologin */ | |
791 opt_nologin = 1; | |
792 break; | |
793 #ifdef _WIN32 | |
794 case 'g': /* debug GTK and GLIB */ | |
795 opt_gdebug = 1; | |
796 break; | |
797 #endif | |
798 case '?': | |
799 default: | |
800 show_usage(1, argv[0]); | |
801 return 0; | |
802 break; | |
803 } | |
804 } | |
805 | |
806 #ifdef _WIN32 | |
807 /* We don't want a console window.. */ | |
808 /* | |
809 * Any calls to the glib logging functions, result in a call to AllocConsole(). | |
810 * ME and 98 will in such cases produce a console window (2000 not), despite | |
811 * being built as a windows app rather than a console app. So we should either | |
812 * ignore messages by setting dummy log handlers, or redirect messages. | |
813 * This requires setting handlers for all domains (any lib which uses g_logging). | |
814 */ | |
815 | |
816 g_log_set_handler (NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, | |
817 (opt_gdebug ? gaim_log_handler : gaim_dummy_log_handler), | |
818 NULL); | |
819 g_log_set_handler ("Gdk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, | |
820 (opt_gdebug ? gaim_log_handler : gaim_dummy_log_handler), | |
821 NULL); | |
822 g_log_set_handler ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, | |
823 (opt_gdebug ? gaim_log_handler : gaim_dummy_log_handler), | |
824 NULL); | |
825 g_log_set_handler ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, | |
826 (opt_gdebug ? gaim_log_handler : gaim_dummy_log_handler), | |
827 NULL); | |
828 g_log_set_handler ("GModule", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, | |
829 (opt_gdebug ? gaim_log_handler : gaim_dummy_log_handler), | |
830 NULL); | |
831 g_log_set_handler ("GLib-GObject", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, | |
832 (opt_gdebug ? gaim_log_handler : gaim_dummy_log_handler), | |
833 NULL); | |
834 g_log_set_handler ("GThread", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, | |
835 (opt_gdebug ? gaim_log_handler : gaim_dummy_log_handler), | |
836 NULL); | |
837 | |
838 /* g_print also makes a call to AllocConsole(), therefore a handler needs to be | |
839 set here aswell */ | |
840 if(!opt_debug) | |
841 g_set_print_handler( gaim_dummy_print ); | |
842 | |
843 #endif | |
844 | |
845 /* show help message */ | |
846 if (opt_help) { | |
847 show_usage(0, argv[0]); | |
848 return 0; | |
849 } | |
850 /* show version message */ | |
851 if (opt_version) { | |
852 printf("Gaim %s\n",VERSION); | |
853 return 0; | |
854 } | |
855 | |
856 #if GAIM_PLUGINS || USE_PERL | |
857 gaim_probe_plugins(); | |
858 #endif | |
859 | |
860 #ifdef _WIN32 | |
861 /* Various win32 initializations */ | |
862 wgaim_init(); | |
863 #endif | |
864 | |
865 load_prefs(); | |
866 core_main(); | |
867 ui_main(); | |
868 | |
869 #ifdef USE_SM | |
870 session_init(argv[0], opt_session_arg); | |
871 #endif | |
872 if (opt_session_arg != NULL) { | |
873 g_free(opt_session_arg); | |
874 opt_session_arg = NULL; | |
875 }; | |
876 | |
877 /* set the default username */ | |
878 if (opt_user_arg != NULL) { | |
879 set_first_user(opt_user_arg); | |
880 g_free(opt_user_arg); | |
881 opt_user_arg = NULL; | |
882 } | |
883 | |
884 if (misc_options & OPT_MISC_DEBUG) | |
885 show_debug(); | |
886 | |
887 static_proto_init(); | |
888 | |
889 /* deal with --login */ | |
890 if (opt_login) { | |
891 dologin_ret = dologin_named(opt_login_arg); | |
892 if (opt_login_arg != NULL) { | |
893 g_free(opt_login_arg); | |
894 opt_login_arg = NULL; | |
895 } | |
896 } | |
897 | |
898 if (!opt_acct && !opt_nologin && gaim_session == 0) | |
899 auto_login(); | |
900 | |
901 if (opt_acct) { | |
902 account_editor(NULL, NULL); | |
903 } else if ((dologin_ret == -1) && !connections) | |
904 show_login(); | |
905 | |
906 gtk_main(); | |
907 core_quit(); | |
4561 | 908 gaim_sound_quit(); |
4489 | 909 #ifdef _WIN32 |
910 wgaim_cleanup(); | |
911 #endif | |
912 return 0; | |
913 | |
914 } |