comparison src/gtkmain.c @ 10302:581de78cf809

[gaim-migrate @ 11487] Rename main.c to gtkmain.c Change POTFILES.in to reflect the new file names Update the po's so they use the new file names Update the po's to use the correct line numbers (or whatever make dist does) committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Thu, 02 Dec 2004 23:48:48 +0000
parents
children 56cc5d49472b
comparison
equal deleted inserted replaced
10301:56b53036e48c 10302:581de78cf809
1 /*
2 * gaim
3 *
4 * Gaim is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24 #include "internal.h"
25 #include "gtkgaim.h"
26
27 #include "account.h"
28 #include "conversation.h"
29 #include "core.h"
30 #include "debug.h"
31 #include "eventloop.h"
32 #include "ft.h"
33 #include "log.h"
34 #include "notify.h"
35 #include "prefs.h"
36 #include "prpl.h"
37 #include "pounce.h"
38 #include "sound.h"
39 #include "status.h"
40 #include "util.h"
41
42 #include "gtkaccount.h"
43 #include "gtkblist.h"
44 #include "gtkconn.h"
45 #include "gtkconv.h"
46 #include "gtkdebug.h"
47 #include "gtkdialogs.h"
48 #include "gtkeventloop.h"
49 #include "gtkft.h"
50 #include "gtknotify.h"
51 #include "gtkplugin.h"
52 #include "gtkpounce.h"
53 #include "gtkprefs.h"
54 #include "gtkprivacy.h"
55 #include "gtkrequest.h"
56 #include "gtkroomlist.h"
57 #include "gtksound.h"
58 #include "gtkstatus.h"
59 #include "gtkutils.h"
60 #include "gtkstock.h"
61
62 #if HAVE_SIGNAL_H
63 # include <signal.h>
64 #endif
65
66 #include <getopt.h>
67
68 #ifdef HAVE_STARTUP_NOTIFICATION
69 # define SN_API_NOT_YET_FROZEN
70 # include <libsn/sn-launchee.h>
71 # include <gdk/gdkx.h>
72 #endif
73
74 static GtkWidget *name;
75 static GtkWidget *pass;
76
77 #ifdef HAVE_STARTUP_NOTIFICATION
78 static SnLauncheeContext *sn_context = NULL;
79 static SnDisplay *sn_display = NULL;
80 #endif
81
82 GtkWidget *mainwindow = NULL;
83
84 int opt_away = 0;
85 int docklet_count = 0;
86 char *opt_away_arg = NULL;
87 int opt_debug = 0;
88
89 #if HAVE_SIGNAL_H
90 /*
91 * Lists of signals we wish to catch and those we wish to ignore.
92 * Each list terminated with -1
93 */
94 static int catch_sig_list[] = {
95 SIGSEGV,
96 SIGHUP,
97 SIGINT,
98 SIGTERM,
99 SIGQUIT,
100 SIGCHLD,
101 -1
102 };
103
104 static int ignore_sig_list[] = {
105 SIGPIPE,
106 -1
107 };
108 #endif
109
110 static guint snd_tmout = 0;
111 static gboolean sound_timeout(gpointer data)
112 {
113 gaim_gtk_sound_set_login_mute(FALSE);
114 snd_tmout = 0;
115 return FALSE;
116 }
117
118 /* we need to do this for Oscar because serv_login only starts the login
119 * process, it doesn't end there. gaim_setup will be called later from
120 * oscar.c, after the buddy list is made and serv_finish_login is called */
121 void gaim_setup(GaimConnection *gc)
122 {
123 if (gaim_prefs_get_bool("/gaim/gtk/sound/enabled/login")) {
124 if (snd_tmout)
125 g_source_remove(snd_tmout);
126 gaim_gtk_sound_set_login_mute(TRUE);
127 snd_tmout = gaim_timeout_add(10000, sound_timeout, NULL);
128 }
129 }
130
131 static gboolean domiddleclick(GtkWidget *w, GdkEventButton *event, gpointer null)
132 {
133 if (event->button != 2)
134 return FALSE;
135
136 gaim_accounts_auto_login(GAIM_GTK_UI);
137
138 return TRUE;
139 }
140
141 static void dologin(GtkWidget *widget, GtkWidget *w)
142 {
143 GaimAccount *account;
144 GtkWidget *item;
145 const char *password = gtk_entry_get_text(GTK_ENTRY(pass));
146
147 item = gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(name))));
148 account = g_object_get_data(G_OBJECT(item), "account");
149
150 if (!account) {
151 gaim_notify_error(NULL, NULL, _("Please create an account."), NULL);
152 return;
153 }
154
155 gaim_account_set_password(account, (*password != '\0') ? password : NULL);
156
157 gaim_account_connect(account);
158 }
159
160 /* <name> is a comma-separated list of names, or NULL
161 if NULL and there is at least one user defined in .gaimrc, try to login.
162 if not NULL, parse <name> into separate strings, look up each one in
163 .gaimrc and, if it's there, try to login.
164 returns: 0 if successful
165 -1 if no user was found that had a saved password
166 */
167 static int dologin_named(char *name)
168 {
169 GaimAccount *account;
170 char **names, **n;
171 int retval = -1;
172
173 if (name !=NULL) { /* list of names given */
174 names = g_strsplit(name, ",", 32);
175 for (n = names; *n != NULL; n++) {
176 account = gaim_accounts_find(*n, NULL);
177 if (account) { /* found a user */
178 retval = 0;
179 gaim_account_connect(account);
180 }
181 }
182 g_strfreev(names);
183 } else { /* no name given, use default */
184 account = (GaimAccount *)gaim_accounts_get_all()->data;
185 retval = 0;
186 gaim_account_connect(account);
187 }
188
189 return retval;
190 }
191
192
193 static void combo_changed(GtkWidget *menu, GaimAccount *account, gpointer data)
194 {
195 if (account && gaim_account_get_remember_password(account)) {
196 gtk_entry_set_text(GTK_ENTRY(pass), account->password);
197 } else {
198 gtk_entry_set_text(GTK_ENTRY(pass), "");
199 }
200 }
201
202
203 static void login_window_closed(GtkWidget *w, GdkEvent *ev, gpointer d)
204 {
205 if(docklet_count) {
206 #ifdef _WIN32
207 wgaim_systray_minimize(mainwindow);
208 #endif
209 gtk_widget_hide(mainwindow);
210 } else
211 gaim_core_quit();
212 }
213
214 void show_login()
215 {
216 GtkWidget *image;
217 GtkWidget *vbox;
218 GtkWidget *button;
219 GtkWidget *hbox;
220 GtkWidget *label;
221 GtkWidget *vbox2;
222
223 /* Do we already have a main window opened? If so, bring it back, baby... ribs... yeah */
224 if (mainwindow) {
225 gtk_window_present(GTK_WINDOW(mainwindow));
226 return;
227 }
228
229 mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
230
231 gtk_window_set_role(GTK_WINDOW(mainwindow), "login");
232 gtk_window_set_resizable(GTK_WINDOW(mainwindow), FALSE);
233 gtk_window_set_title(GTK_WINDOW(mainwindow), _("Login"));
234 gtk_container_set_border_width(GTK_CONTAINER(mainwindow), 5);
235 g_signal_connect(G_OBJECT(mainwindow), "delete_event",
236 G_CALLBACK(login_window_closed), mainwindow);
237
238 vbox = gtk_vbox_new(FALSE, 0);
239 gtk_container_add(GTK_CONTAINER(mainwindow), vbox);
240
241 image = gtk_image_new_from_stock(GAIM_STOCK_LOGO, gtk_icon_size_from_name(GAIM_ICON_SIZE_LOGO));
242 gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0);
243
244 vbox2 = gtk_vbox_new(FALSE, 0);
245 gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5);
246
247 /* why isn't there a gtk_label_new_with_markup? */
248 label = gtk_label_new(NULL);
249 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("<b>_Account:</b>"));
250 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
251 gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0);
252
253 name = gaim_gtk_account_option_menu_new(NULL, TRUE, G_CALLBACK(combo_changed), NULL, NULL);
254 gtk_label_set_mnemonic_widget(GTK_LABEL(label), name);
255
256 gtk_box_pack_start(GTK_BOX(vbox2), name, FALSE, TRUE, 0);
257 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, TRUE, 0);
258
259 vbox2 = gtk_vbox_new(FALSE, 0);
260 gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5);
261
262 label = gtk_label_new(NULL);
263 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("<b>_Password:</b>"));
264 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
265 gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0);
266
267 pass = gtk_entry_new();
268 gtk_label_set_mnemonic_widget(GTK_LABEL(label), pass);
269 gtk_entry_set_visibility(GTK_ENTRY(pass), FALSE);
270 g_signal_connect(G_OBJECT(pass), "activate",
271 G_CALLBACK(dologin), mainwindow);
272 gtk_box_pack_start(GTK_BOX(vbox2), pass, FALSE, TRUE, 0);
273 gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, TRUE, 0);
274
275 /* Now for the button box */
276 hbox = gtk_hbox_new(TRUE, 0);
277 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 5);
278
279 /* And now for the buttons */
280 button = gaim_pixbuf_button_from_stock(_("A_ccounts"), GAIM_STOCK_ACCOUNTS, GAIM_BUTTON_VERTICAL);
281 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
282 g_signal_connect(G_OBJECT(button), "clicked",
283 G_CALLBACK(gaim_gtk_accounts_window_show), mainwindow);
284 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
285
286 button = gaim_pixbuf_button_from_stock(_("P_references"), GTK_STOCK_PREFERENCES, GAIM_BUTTON_VERTICAL);
287 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
288 g_signal_connect(G_OBJECT(button), "clicked",
289 G_CALLBACK(gaim_gtk_prefs_show), mainwindow);
290 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
291
292 button = gaim_pixbuf_button_from_stock(_("_Log in"), GAIM_STOCK_SIGN_ON, GAIM_BUTTON_VERTICAL);
293 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
294 g_signal_connect(G_OBJECT(button), "clicked",
295 G_CALLBACK(dologin), mainwindow);
296 g_signal_connect(G_OBJECT(button), "button-press-event", G_CALLBACK(domiddleclick), NULL);
297 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
298
299 /* Now grab the focus that we need */
300 if (gaim_accounts_get_all()) {
301 GaimAccount *account = gaim_accounts_get_all()->data;
302
303 if (gaim_account_get_remember_password(account)) {
304 combo_changed(NULL, account, NULL);
305 gtk_widget_grab_focus(button);
306 } else {
307 gtk_widget_grab_focus(pass);
308 }
309 } else {
310 gaim_gtk_accounts_window_show();
311 gtk_widget_grab_focus(button);
312 }
313
314 /* And raise the curtain! */
315 gtk_widget_show_all(mainwindow);
316
317 /* XXX - TODO - STATUS - Remove this! */
318 gaim_gtk_status_window_show();
319 }
320
321 static void
322 clean_pid(void)
323 {
324 #ifndef _WIN32
325 int status;
326 pid_t pid;
327
328 do {
329 pid = waitpid(-1, &status, WNOHANG);
330 } while (pid != 0 && pid != (pid_t)-1);
331 if(pid == (pid_t)-1 && errno != ECHILD) {
332 char errmsg[BUFSIZ];
333 snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
334 perror(errmsg);
335 }
336 #endif
337 }
338
339 #if HAVE_SIGNAL_H
340 void sighandler(int sig)
341 {
342 switch (sig) {
343 case SIGHUP:
344 gaim_debug(GAIM_DEBUG_WARNING, "sighandler",
345 "Caught signal %d\n", sig);
346 gaim_connections_disconnect_all();
347 break;
348 case SIGSEGV:
349 #ifndef DEBUG
350 fprintf(stderr, "Gaim has segfaulted and attempted to dump a core file.\n"
351 "This is a bug in the software and has happened through\n"
352 "no fault of your own.\n\n"
353 "It is possible that this bug is already fixed in CVS.\n"
354 "If you can reproduce the crash, please notify the gaim\n"
355 "maintainers by reporting a bug at\n"
356 GAIM_WEBSITE "bug.php\n\n"
357 "Please make sure to specify what you were doing at the time,\n"
358 "and post the backtrace from the core file. If you do not know\n"
359 "how to get the backtrace, please get instructions at\n"
360 GAIM_WEBSITE "gdb.php. If you need further\n"
361 "assistance, please IM either RobFlynn or SeanEgn and\n"
362 "they can help you.\n");
363 #else
364 fprintf(stderr, "Hi, user. We need to talk.\n"
365 "I think something's gone wrong here. It's probably my fault.\n"
366 "No, really, it's not you... it's me... no no no, I think we get along well\n"
367 "it's just that.... well, I want to see other people. I... what?!? NO! I haven't\n"
368 "been cheating on you!! How many times do you want me to tell you?! And for the\n"
369 "last time, it's just a rash!\n");
370 /*g_on_error_query (g_get_prgname());*/
371 #endif
372 abort();
373 break;
374 case SIGCHLD:
375 clean_pid();
376 #if HAVE_SIGNAL_H
377 signal(SIGCHLD, sighandler); /* restore signal catching on this one! */
378 #endif
379 break;
380 default:
381 gaim_debug(GAIM_DEBUG_WARNING, "sighandler",
382 "Caught signal %d\n", sig);
383 gaim_connections_disconnect_all();
384
385 gaim_plugins_unload_all();
386
387 if (gtk_main_level())
388 gtk_main_quit();
389 exit(0);
390 }
391 }
392 #endif
393
394 static int ui_main()
395 {
396 #ifndef _WIN32
397 GList *icons = NULL;
398 GdkPixbuf *icon = NULL;
399 char *icon_path;
400 #endif
401
402 if (current_smiley_theme == NULL) {
403 smiley_theme_probe();
404 if (smiley_themes) {
405 struct smiley_theme *smile = smiley_themes->data;
406 load_smiley_theme(smile->path, TRUE);
407 }
408 }
409
410 gaim_gtk_blist_setup_sort_methods();
411
412 #ifndef _WIN32
413 /* use the nice PNG icon for all the windows */
414 icon_path = g_build_filename(DATADIR, "pixmaps", "gaim", "icons", "online.png", NULL);
415 icon = gdk_pixbuf_new_from_file(icon_path, NULL);
416 g_free(icon_path);
417 if (icon) {
418 icons = g_list_append(icons,icon);
419 gtk_window_set_default_icon_list(icons);
420 g_object_unref(G_OBJECT(icon));
421 g_list_free(icons);
422 } else {
423 gaim_debug(GAIM_DEBUG_ERROR, "ui_main",
424 "Failed to load the default window icon!\n");
425 }
426 #endif
427
428 return 0;
429 }
430
431 static void set_first_user(const char *name)
432 {
433 GaimAccount *account;
434
435 account = gaim_accounts_find(name, NULL);
436
437 /* Place it as the first user. */
438 if (account != NULL)
439 gaim_accounts_reorder(account, 0);
440 }
441
442 static void
443 debug_init(void)
444 {
445 gaim_debug_set_ui_ops(gaim_gtk_debug_get_ui_ops());
446 gaim_gtk_debug_init();
447 }
448
449 static void
450 gaim_gtk_ui_init(void)
451 {
452 /* Set the UI operation structures. */
453 gaim_accounts_set_ui_ops(gaim_gtk_accounts_get_ui_ops());
454 gaim_conversations_set_win_ui_ops(gaim_gtk_conversations_get_win_ui_ops());
455 gaim_xfers_set_ui_ops(gaim_gtk_xfers_get_ui_ops());
456 gaim_blist_set_ui_ops(gaim_gtk_blist_get_ui_ops());
457 gaim_notify_set_ui_ops(gaim_gtk_notify_get_ui_ops());
458 gaim_privacy_set_ui_ops(gaim_gtk_privacy_get_ui_ops());
459 gaim_request_set_ui_ops(gaim_gtk_request_get_ui_ops());
460 gaim_sound_set_ui_ops(gaim_gtk_sound_get_ui_ops());
461 gaim_connections_set_ui_ops(gaim_gtk_connections_get_ui_ops());
462
463 gaim_gtk_stock_init();
464 gaim_gtk_prefs_init();
465 gaim_gtk_account_init();
466 gaim_gtk_blist_init();
467 gaim_gtk_conversations_init();
468 gaim_gtk_pounces_init();
469 gaim_gtk_privacy_init();
470 gaim_gtk_status_init();
471 gaim_gtk_xfers_init();
472 gaim_gtk_roomlist_init();
473 }
474
475 static void
476 gaim_gtk_quit(void)
477 {
478 /* XXX? */
479 /* YYY is there an XXX here? */
480
481 /* captain's log, stardate... */
482 /* LOG system_log(log_quit, NULL, NULL, OPT_LOG_BUDDY_SIGNON | OPT_LOG_MY_SIGNON); */
483
484 #ifdef USE_SM
485 /* unplug */
486 session_end();
487 #endif
488
489 /* Save the plugins we have loaded for next time. */
490 gaim_gtk_plugins_save();
491
492 /* and end it all... */
493 gtk_main_quit();
494 }
495
496 static GaimCoreUiOps core_ops =
497 {
498 gaim_gtk_prefs_init,
499 debug_init,
500 gaim_gtk_ui_init,
501 gaim_gtk_quit
502 };
503
504 static GaimCoreUiOps *
505 gaim_gtk_core_get_ui_ops(void)
506 {
507 return &core_ops;
508 }
509
510 static void
511 show_usage(int mode, const char *name)
512 {
513 char *text=NULL;
514
515 switch (mode) {
516 case 0: /* full help text */
517 text=g_strdup_printf(_("Gaim %s\n"
518 "Usage: %s [OPTION]...\n\n"
519 " -a, --acct display account editor window\n"
520 " -w, --away[=MESG] make away on signon (optional argument MESG specifies\n"
521 " name of away message to use)\n"
522 " -l, --login[=NAME] automatically login (optional argument NAME specifies\n"
523 " account(s) to use, seperated by commas)\n"
524 " -n, --loginwin don't automatically login; show login window\n"
525 " -u, --user=NAME use account NAME\n"
526 " -c, --config=DIR use DIR for config files\n"
527 " -d, --debug print debugging messages to stdout\n"
528 " -v, --version display the current version and exit\n"
529 " -h, --help display this help and exit\n"), VERSION, name);
530 break;
531 case 1: /* short message */
532 text=g_strdup_printf(_("Gaim %s. Try `%s -h' for more information.\n"), VERSION, name);
533 break;
534 }
535
536 if(text) {
537 char *text_conv;
538 GError *error=NULL;
539
540 /* tries to convert 'text' to users locale */
541 text_conv=g_locale_from_utf8(text,-1,NULL,NULL,&error);
542 if(text_conv) {
543 puts(text_conv);
544 g_free(text_conv);
545 }
546 /* use 'text' as a fallback */
547 else {
548 g_warning("%s\n", error->message);
549 g_error_free(error);
550 puts(text);
551 }
552 g_free(text);
553 }
554 }
555
556 #ifdef HAVE_STARTUP_NOTIFICATION
557 static void
558 sn_error_trap_push(SnDisplay *display, Display *xdisplay)
559 {
560 gdk_error_trap_push();
561 }
562
563 static void
564 sn_error_trap_pop(SnDisplay *display, Display *xdisplay)
565 {
566 gdk_error_trap_pop();
567 }
568
569 static void
570 startup_notification_complete(void)
571 {
572 Display *xdisplay;
573
574 xdisplay = GDK_DISPLAY();
575 sn_display = sn_display_new(xdisplay,
576 sn_error_trap_push,
577 sn_error_trap_pop);
578 sn_context =
579 sn_launchee_context_new_from_environment(sn_display,
580 DefaultScreen(xdisplay));
581
582 if (sn_context != NULL)
583 {
584 sn_launchee_context_complete(sn_context);
585 sn_launchee_context_unref(sn_context);
586
587 sn_display_unref(sn_display);
588 }
589 }
590 #endif /* HAVE_STARTUP_NOTIFICATION */
591
592 #ifndef _WIN32
593 static char *gaim_find_binary_location(void *symbol, void *data)
594 {
595 static char *fullname = NULL;
596 static gboolean first = TRUE;
597
598 char *argv0 = data;
599 struct stat st;
600 char *basebuf, *linkbuf, *fullbuf;
601
602 if (!first)
603 /* We've already been through this. */
604 return strdup(fullname);
605
606 first = FALSE;
607
608 if (!argv0)
609 return NULL;
610
611
612 basebuf = g_find_program_in_path(argv0);
613
614 /* But we still need to deal with symbolic links */
615 lstat(basebuf, &st);
616 while ((st.st_mode & S_IFLNK) == S_IFLNK) {
617 linkbuf = g_malloc(1024);
618 readlink(basebuf, linkbuf, 1024);
619 if (linkbuf[0] == G_DIR_SEPARATOR) {
620 /* an absolute path */
621 fullbuf = g_strdup(linkbuf);
622 } else {
623 char *dirbuf = g_path_get_dirname(basebuf);
624 /* a relative path */
625 fullbuf = g_strdup_printf("%s%s%s",
626 dirbuf, G_DIR_SEPARATOR_S,
627 linkbuf);
628 g_free(dirbuf);
629 }
630 /* There's no memory leak here. Really! */
631 g_free(linkbuf);
632 g_free(basebuf);
633 basebuf = fullbuf;
634 lstat(basebuf, &st);
635 }
636
637 fullname = basebuf;
638 return strdup(fullname);
639 }
640 #endif /* #ifndef _WIN32 */
641
642 /* FUCKING GET ME A TOWEL! */
643 #ifdef _WIN32
644 int gaim_main(HINSTANCE hint, int argc, char *argv[])
645 #else
646 int main(int argc, char *argv[])
647 #endif
648 {
649 int opt_acct = 0, opt_help = 0, opt_version = 0, opt_login = 0, opt_nologin = 0, dologin_ret = -1;
650 char *opt_user_arg = NULL, *opt_login_arg = NULL;
651 char *opt_session_arg = NULL, *opt_config_dir_arg = NULL;
652 char *plugin_search_paths[3];
653 #if HAVE_SIGNAL_H
654 int sig_indx; /* for setting up signal catching */
655 sigset_t sigset;
656 void (*prev_sig_disp)();
657 #endif
658 int opt, opt_user = 0;
659 int i;
660 gboolean gui_check;
661 gchar *gaimrc, *accountsxml;
662
663 struct option long_options[] = {
664 {"acct", no_argument, NULL, 'a'},
665 /*{"away", optional_argument, NULL, 'w'}, */
666 {"help", no_argument, NULL, 'h'},
667 /*{"login", optional_argument, NULL, 'l'}, */
668 {"loginwin", no_argument, NULL, 'n'},
669 {"user", required_argument, NULL, 'u'},
670 {"config", required_argument, NULL, 'c'},
671 {"debug", no_argument, NULL, 'd'},
672 {"version", no_argument, NULL, 'v'},
673 {"session", required_argument, NULL, 's'},
674 {0, 0, 0, 0}
675 };
676
677 #ifdef DEBUG
678 opt_debug = 1;
679 #endif
680 #ifndef _WIN32
681 br_set_locate_fallback_func(gaim_find_binary_location, argv[0]);
682 #endif
683 #ifdef ENABLE_NLS
684 bindtextdomain(PACKAGE, LOCALEDIR);
685 bind_textdomain_codeset(PACKAGE, "UTF-8");
686 textdomain(PACKAGE);
687 #endif
688
689 #if HAVE_SIGNAL_H
690 /* Let's not violate any PLA's!!!! */
691 /* jseymour: whatever the fsck that means */
692 /* Robot101: for some reason things like gdm like to block *
693 * useful signals like SIGCHLD, so we unblock all the ones we *
694 * declare a handler for. thanks JSeymour and Vann. */
695 if (sigemptyset(&sigset)) {
696 char errmsg[BUFSIZ];
697 snprintf(errmsg, BUFSIZ, "Warning: couldn't initialise empty signal set");
698 perror(errmsg);
699 }
700 for(sig_indx = 0; catch_sig_list[sig_indx] != -1; ++sig_indx) {
701 if((prev_sig_disp = signal(catch_sig_list[sig_indx], sighandler)) == SIG_ERR) {
702 char errmsg[BUFSIZ];
703 snprintf(errmsg, BUFSIZ, "Warning: couldn't set signal %d for catching",
704 catch_sig_list[sig_indx]);
705 perror(errmsg);
706 }
707 if(sigaddset(&sigset, catch_sig_list[sig_indx])) {
708 char errmsg[BUFSIZ];
709 snprintf(errmsg, BUFSIZ, "Warning: couldn't include signal %d for unblocking",
710 catch_sig_list[sig_indx]);
711 perror(errmsg);
712 }
713 }
714 for(sig_indx = 0; ignore_sig_list[sig_indx] != -1; ++sig_indx) {
715 if((prev_sig_disp = signal(ignore_sig_list[sig_indx], SIG_IGN)) == SIG_ERR) {
716 char errmsg[BUFSIZ];
717 snprintf(errmsg, BUFSIZ, "Warning: couldn't set signal %d to ignore",
718 ignore_sig_list[sig_indx]);
719 perror(errmsg);
720 }
721 }
722
723 if (sigprocmask(SIG_UNBLOCK, &sigset, NULL)) {
724 char errmsg[BUFSIZ];
725 snprintf(errmsg, BUFSIZ, "Warning: couldn't unblock signals");
726 perror(errmsg);
727 }
728 #endif
729
730 for (i = 0; i < argc; i++) {
731 /* --login option */
732 if (strstr(argv[i], "--l") == argv[i]) {
733 char *equals;
734 opt_login = 1;
735 if ((equals = strchr(argv[i], '=')) != NULL) {
736 /* --login=NAME */
737 opt_login_arg = g_strdup(equals + 1);
738 if (strlen(opt_login_arg) == 0) {
739 g_free(opt_login_arg);
740 opt_login_arg = NULL;
741 }
742 } else if (i + 1 < argc && argv[i + 1][0] != '-') {
743 /* --login NAME */
744 opt_login_arg = g_strdup(argv[i + 1]);
745 strcpy(argv[i + 1], " ");
746 }
747 strcpy(argv[i], " ");
748 }
749 /* -l option */
750 else if (strstr(argv[i], "-l") == argv[i]) {
751 opt_login = 1;
752 if (strlen(argv[i]) > 2) {
753 /* -lNAME */
754 opt_login_arg = g_strdup(argv[i] + 2);
755 } else if (i + 1 < argc && argv[i + 1][0] != '-') {
756 /* -l NAME */
757 opt_login_arg = g_strdup(argv[i + 1]);
758 strcpy(argv[i + 1], " ");
759 }
760 strcpy(argv[i], " ");
761 }
762 /* --away option */
763 else if (strstr(argv[i], "--aw") == argv[i]) {
764 char *equals;
765 opt_away = 1;
766 if ((equals = strchr(argv[i], '=')) != NULL) {
767 /* --away=MESG */
768 opt_away_arg = g_strdup(equals + 1);
769 if (strlen(opt_away_arg) == 0) {
770 g_free(opt_away_arg);
771 opt_away_arg = NULL;
772 }
773 } else if (i + 1 < argc && argv[i + 1][0] != '-') {
774 /* --away MESG */
775 opt_away_arg = g_strdup(argv[i + 1]);
776 strcpy(argv[i + 1], " ");
777 }
778 strcpy(argv[i], " ");
779 }
780 /* -w option */
781 else if (strstr(argv[i], "-w") == argv[i]) {
782 opt_away = 1;
783 if (strlen(argv[i]) > 2) {
784 /* -wMESG */
785 opt_away_arg = g_strdup(argv[i] + 2);
786 } else if (i + 1 < argc && argv[i + 1][0] != '-') {
787 /* -w MESG */
788 opt_away_arg = g_strdup(argv[i + 1]);
789 strcpy(argv[i + 1], " ");
790 }
791 strcpy(argv[i], " ");
792 }
793 }
794 /*
795 if (opt_login) {
796 printf ("--login given with arg %s\n",
797 opt_login_arg ? opt_login_arg : "NULL");
798 exit(0);
799 }
800 */
801
802 gui_check = gtk_init_check(&argc, &argv);
803
804 /* scan command-line options */
805 opterr = 1;
806 while ((opt = getopt_long(argc, argv,
807 #ifndef _WIN32
808 "adhu:c:vns:",
809 #else
810 "adhu:c:vn",
811 #endif
812 long_options, NULL)) != -1) {
813 switch (opt) {
814 case 'u': /* set user */
815 opt_user = 1;
816 opt_user_arg = g_strdup(optarg);
817 break;
818 case 'a': /* account editor */
819 opt_acct = 1;
820 break;
821 case 'd': /* debug */
822 opt_debug = 1;
823 break;
824 case 'c': /* use specified config dir */
825 set_gaim_user_dir(optarg);
826 opt_config_dir_arg = g_strdup(optarg);
827 break;
828 case 's': /* use existing session ID */
829 opt_session_arg = g_strdup(optarg);
830 break;
831 case 'v': /* version */
832 opt_version = 1;
833 break;
834 case 'h': /* help */
835 opt_help = 1;
836 break;
837 case 'n': /* don't autologin */
838 opt_nologin = 1;
839 break;
840 case '?':
841 default:
842 show_usage(1, argv[0]);
843 return 0;
844 break;
845 }
846 }
847
848 /* show help message */
849 if (opt_help) {
850 show_usage(0, argv[0]);
851 return 0;
852 }
853 /* show version message */
854 if (opt_version) {
855 printf("Gaim %s\n",VERSION);
856 return 0;
857 }
858
859 if (!gui_check) {
860 char *display = gdk_get_display();
861
862 g_warning("cannot open display: %s", display ? display : "unset");
863 g_free(display);
864
865 return 1;
866 }
867
868 #ifdef _WIN32
869 wgaim_init(hint);
870 #endif
871 gaim_core_set_ui_ops(gaim_gtk_core_get_ui_ops());
872 gaim_eventloop_set_ui_ops(gaim_gtk_eventloop_get_ui_ops());
873
874 if (!gaim_core_init(GAIM_GTK_UI)) {
875 fprintf(stderr,
876 "Initialization of the Gaim core failed. Dumping core.\n"
877 "Please report this!\n");
878 abort();
879 }
880
881 plugin_search_paths[0] = g_strdup(LIBDIR);
882 plugin_search_paths[1] = gaim_user_dir();
883 plugin_search_paths[2] = g_build_filename(gaim_user_dir(), "plugins", NULL);
884
885 gaim_plugins_set_search_paths(sizeof(plugin_search_paths) /
886 sizeof(*plugin_search_paths),
887 plugin_search_paths);
888
889 g_free(plugin_search_paths[0]);
890 g_free(plugin_search_paths[2]);
891
892 gaim_plugins_probe(NULL);
893
894 /* XXX - Remove this check. Maybe in 2005. --KingAnt, 25 Jul 2004 */
895 gaimrc = g_build_filename(gaim_home_dir(), ".gaimrc", NULL);
896 accountsxml = g_build_filename(gaim_user_dir(), "accounts.xml", NULL);
897 if (g_file_test(gaimrc, G_FILE_TEST_EXISTS) &&
898 !g_file_test(accountsxml, G_FILE_TEST_EXISTS)) {
899 gaim_notify_error(NULL, NULL, _("Unable to load preferences"), _("Gaim was not able to load your preferences because they are stored in an old format that is no longer used. Please reconfigure your settings using the Preferences window."));
900 }
901 g_free(gaimrc);
902 g_free(accountsxml);
903
904 gaim_accounts_load();
905
906 gaim_set_blist(gaim_blist_new());
907 gaim_blist_load();
908
909 gaim_prefs_load();
910
911 gaim_prefs_update_old();
912 gaim_gtk_prefs_update_old();
913
914 /* load plugins we had when we quit */
915 gaim_plugins_load_saved("/gaim/gtk/plugins/loaded");
916
917 gaim_pounces_load();
918 gaim_statuses_load();
919
920 ui_main();
921
922 #ifdef USE_SM
923 session_init(argv[0], opt_session_arg, opt_config_dir_arg);
924 #endif
925 if (opt_session_arg != NULL) {
926 g_free(opt_session_arg);
927 opt_session_arg = NULL;
928 }
929
930 if (opt_config_dir_arg != NULL) {
931 g_free(opt_config_dir_arg);
932 opt_config_dir_arg = NULL;
933 }
934
935 /* set the default username */
936 if (opt_user_arg != NULL) {
937 set_first_user(opt_user_arg);
938 g_free(opt_user_arg);
939 opt_user_arg = NULL;
940 }
941
942 if (gaim_prefs_get_bool("/gaim/gtk/debug/enabled"))
943 gaim_gtk_debug_window_show();
944
945 /* deal with --login */
946 if (opt_login) {
947 dologin_ret = dologin_named(opt_login_arg);
948 if (opt_login_arg != NULL) {
949 g_free(opt_login_arg);
950 opt_login_arg = NULL;
951 }
952 }
953
954 if (!opt_acct && !opt_nologin)
955 gaim_accounts_auto_login(GAIM_GTK_UI);
956
957 if (opt_acct) {
958 gaim_gtk_accounts_window_show();
959 } else if ((dologin_ret == -1) && !gaim_connections_get_all())
960 show_login();
961
962 #ifdef HAVE_STARTUP_NOTIFICATION
963 startup_notification_complete();
964 #endif
965 gtk_main();
966 gaim_sound_shutdown();
967 #ifdef _WIN32
968 wgaim_cleanup();
969 #endif
970
971
972 return 0;
973
974 }