gee
oldstatus
2005-09-19, Nathan Walp
* 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 * 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 "conversation.h" #include "gtkeventloop.h" #ifdef HAVE_STARTUP_NOTIFICATION # define SN_API_NOT_YET_FROZEN # include <libsn/sn-launchee.h> #ifdef HAVE_STARTUP_NOTIFICATION static SnLauncheeContext * sn_context = NULL ; static SnDisplay * sn_display = NULL ; GtkWidget * mainwindow = NULL ; char * opt_away_arg = NULL ; * Lists of signals we wish to catch and those we wish to ignore. * Each list terminated with -1 static int catch_sig_list [] = { static int ignore_sig_list [] = { static guint snd_tmout = 0 ; static gboolean sound_timeout ( gpointer data ) gaim_gtk_sound_set_login_mute ( FALSE ); /* we need to do this for Oscar because serv_login only starts the login * process, it doesn't end there. gaim_setup will be called later from * oscar.c, after the buddy list is made and serv_finish_login is called */ void gaim_setup ( GaimConnection * gc ) if ( gaim_prefs_get_bool ( "/gaim/gtk/sound/enabled/login" )) { g_source_remove ( snd_tmout ); gaim_gtk_sound_set_login_mute ( TRUE ); snd_tmout = gaim_timeout_add ( 10000 , sound_timeout , NULL ); static gboolean domiddleclick ( GtkWidget * w , GdkEventButton * event , gpointer null ) gaim_accounts_auto_login ( GAIM_GTK_UI ); static void dologin ( GtkWidget * widget , GtkWidget * w ) const char * password = gtk_entry_get_text ( GTK_ENTRY ( pass )); item = gtk_menu_get_active ( GTK_MENU ( gtk_option_menu_get_menu ( GTK_OPTION_MENU ( name )))); account = g_object_get_data ( G_OBJECT ( item ), "account" ); gaim_notify_error ( NULL , NULL , _ ( "Please create an account." ), NULL ); gaim_account_set_password ( account , ( * password != '\0' ) ? password : NULL ); gaim_account_connect ( account ); /* <name> is a comma-separated list of names, or NULL if NULL and there is at least one user defined in .gaimrc, try to login. if not NULL, parse <name> into separate strings, look up each one in .gaimrc and, if it's there, try to login. -1 if no user was found that had a saved password static int dologin_named ( char * name ) if ( name != NULL ) { /* list of names given */ names = g_strsplit ( name , "," , 32 ); for ( n = names ; * n != NULL ; n ++ ) { account = gaim_accounts_find ( * n , NULL ); if ( account ) { /* found a user */ gaim_account_connect ( account ); } else { /* no name given, use default */ account = ( GaimAccount * ) gaim_accounts_get_all () -> data ; gaim_account_connect ( account ); static void combo_changed ( GtkWidget * menu , GaimAccount * account , gpointer data ) if ( account && gaim_account_get_remember_password ( account )) { gtk_entry_set_text ( GTK_ENTRY ( pass ), account -> password ); gtk_entry_set_text ( GTK_ENTRY ( pass ), "" ); static void login_window_closed ( GtkWidget * w , GdkEvent * ev , gpointer d ) wgaim_systray_minimize ( mainwindow ); gtk_widget_hide ( mainwindow ); /* Do we already have a main window opened? If so, bring it back, baby... ribs... yeah */ gtk_window_present ( GTK_WINDOW ( mainwindow )); mainwindow = gtk_window_new ( GTK_WINDOW_TOPLEVEL ); gtk_window_set_role ( GTK_WINDOW ( mainwindow ), "login" ); gtk_window_set_resizable ( GTK_WINDOW ( mainwindow ), FALSE ); gtk_window_set_title ( GTK_WINDOW ( mainwindow ), _ ( "Login" )); gtk_container_set_border_width ( GTK_CONTAINER ( mainwindow ), 5 ); g_signal_connect ( G_OBJECT ( mainwindow ), "delete_event" , G_CALLBACK ( login_window_closed ), mainwindow ); vbox = gtk_vbox_new ( FALSE , 0 ); gtk_container_add ( GTK_CONTAINER ( mainwindow ), vbox ); image = gtk_image_new_from_stock ( GAIM_STOCK_LOGO , gtk_icon_size_from_name ( GAIM_ICON_SIZE_LOGO )); gtk_box_pack_start ( GTK_BOX ( vbox ), image , FALSE , FALSE , 0 ); vbox2 = gtk_vbox_new ( FALSE , 0 ); gtk_container_set_border_width ( GTK_CONTAINER ( vbox2 ), 5 ); /* why isn't there a gtk_label_new_with_markup? */ label = gtk_label_new ( NULL ); gtk_label_set_markup_with_mnemonic ( GTK_LABEL ( label ), _ ( "<b>_Account:</b>" )); gtk_misc_set_alignment ( GTK_MISC ( label ), 0 , 0.5 ); gtk_box_pack_start ( GTK_BOX ( vbox2 ), label , FALSE , FALSE , 0 ); name = gaim_gtk_account_option_menu_new ( NULL , TRUE , G_CALLBACK ( combo_changed ), NULL , NULL ); gtk_label_set_mnemonic_widget ( GTK_LABEL ( label ), name ); gtk_box_pack_start ( GTK_BOX ( vbox2 ), name , FALSE , TRUE , 0 ); gtk_box_pack_start ( GTK_BOX ( vbox ), vbox2 , FALSE , TRUE , 0 ); vbox2 = gtk_vbox_new ( FALSE , 0 ); gtk_container_set_border_width ( GTK_CONTAINER ( vbox2 ), 5 ); label = gtk_label_new ( NULL ); gtk_label_set_markup_with_mnemonic ( GTK_LABEL ( label ), _ ( "<b>_Password:</b>" )); gtk_misc_set_alignment ( GTK_MISC ( label ), 0 , 0.5 ); gtk_box_pack_start ( GTK_BOX ( vbox2 ), label , FALSE , FALSE , 0 ); gtk_label_set_mnemonic_widget ( GTK_LABEL ( label ), pass ); gtk_entry_set_visibility ( GTK_ENTRY ( pass ), FALSE ); g_signal_connect ( G_OBJECT ( pass ), "activate" , G_CALLBACK ( dologin ), mainwindow ); gtk_box_pack_start ( GTK_BOX ( vbox2 ), pass , FALSE , TRUE , 0 ); gtk_box_pack_start ( GTK_BOX ( vbox ), vbox2 , FALSE , TRUE , 0 ); /* Now for the button box */ hbox = gtk_hbox_new ( TRUE , 0 ); gtk_box_pack_start ( GTK_BOX ( vbox ), hbox , FALSE , TRUE , 5 ); /* And now for the buttons */ button = gaim_pixbuf_button_from_stock ( _ ( "A_ccounts" ), GAIM_STOCK_ACCOUNTS , GAIM_BUTTON_VERTICAL ); gtk_button_set_relief ( GTK_BUTTON ( button ), GTK_RELIEF_NONE ); g_signal_connect ( G_OBJECT ( button ), "clicked" , G_CALLBACK ( gaim_gtk_accounts_window_show ), mainwindow ); gtk_box_pack_start ( GTK_BOX ( hbox ), button , FALSE , FALSE , 0 ); button = gaim_pixbuf_button_from_stock ( _ ( "P_references" ), GTK_STOCK_PREFERENCES , GAIM_BUTTON_VERTICAL ); gtk_button_set_relief ( GTK_BUTTON ( button ), GTK_RELIEF_NONE ); g_signal_connect ( G_OBJECT ( button ), "clicked" , G_CALLBACK ( gaim_gtk_prefs_show ), mainwindow ); gtk_box_pack_start ( GTK_BOX ( hbox ), button , FALSE , FALSE , 0 ); button = gaim_pixbuf_button_from_stock ( _ ( "_Sign on" ), GAIM_STOCK_SIGN_ON , GAIM_BUTTON_VERTICAL ); gtk_button_set_relief ( GTK_BUTTON ( button ), GTK_RELIEF_NONE ); g_signal_connect ( G_OBJECT ( button ), "clicked" , G_CALLBACK ( dologin ), mainwindow ); g_signal_connect ( G_OBJECT ( button ), "button-press-event" , G_CALLBACK ( domiddleclick ), NULL ); gtk_box_pack_start ( GTK_BOX ( hbox ), button , FALSE , FALSE , 0 ); /* Now grab the focus that we need */ if ( gaim_accounts_get_all ()) { GaimAccount * account = gaim_accounts_get_all () -> data ; if ( gaim_account_get_remember_password ( account )) { combo_changed ( NULL , account , NULL ); gtk_widget_grab_focus ( button ); gtk_widget_grab_focus ( pass ); gaim_gtk_accounts_window_show (); gtk_widget_grab_focus ( button ); /* And raise the curtain! */ gtk_widget_show_all ( mainwindow ); pid = waitpid ( -1 , & status , WNOHANG ); } while ( pid != 0 && pid != ( pid_t ) -1 ); if (( pid == ( pid_t ) - 1 ) && ( errno != ECHILD )) { snprintf ( errmsg , BUFSIZ , "Warning: waitpid() returned %d" , pid ); gaim_debug_warning ( "sighandler" , "Caught signal %d \n " , sig ); gaim_connections_disconnect_all (); fprintf ( stderr , "Gaim has segfaulted and attempted to dump a core file. \n " "This is a bug in the software and has happened through \n " "no fault of your own. \n\n " "It is possible that this bug is already fixed in CVS. \n " "If you can reproduce the crash, please notify the gaim \n " "maintainers by reporting a bug at \n " GAIM_WEBSITE "bug.php \n\n " "Please make sure to specify what you were doing at the time, \n " "and post the backtrace from the core file. If you do not know \n " "how to get the backtrace, please get instructions at \n " GAIM_WEBSITE "gdb.php. If you need further \n " "assistance, please IM either SeanEgn or LSchiere and \n " fprintf ( stderr , "Hi, user. We need to talk. \n " "I think something's gone wrong here. It's probably my fault. \n " "No, really, it's not you... it's me... no no no, I think we get along well \n " "it's just that.... well, I want to see other people. I... what?!? NO! I haven't \n " "been cheating on you!! How many times do you want me to tell you?! And for the \n " "last time, it's just a rash! \n " ); /*g_on_error_query (g_get_prgname());*/ signal ( SIGCHLD , sighandler ); /* restore signal catching on this one! */ gaim_debug_warning ( "sighandler" , "Caught signal %d \n " , sig ); gaim_connections_disconnect_all (); gaim_plugins_unload_all (); if ( current_smiley_theme == NULL ) { struct smiley_theme * smile = smiley_themes -> data ; load_smiley_theme ( smile -> path , TRUE ); gaim_gtk_blist_setup_sort_methods (); /* use the nice PNG icon for all the windows */ icon_path = g_build_filename ( DATADIR , "pixmaps" , "gaim" , "icons" , "online.png" , NULL ); icon = gdk_pixbuf_new_from_file ( icon_path , NULL ); icons = g_list_append ( icons , icon ); gtk_window_set_default_icon_list ( icons ); g_object_unref ( G_OBJECT ( icon )); gaim_debug ( GAIM_DEBUG_ERROR , "ui_main" , "Failed to load the default window icon! \n " ); static void set_first_user ( char * name ) account = gaim_accounts_find ( name , NULL ); if ( account == NULL ) { /* new user */ account = gaim_account_new ( name , GAIM_PROTO_DEFAULT ); gaim_accounts_add ( account ); /* Place it as the first user. */ gaim_accounts_reorder ( account , 0 ); gaim_debug_set_ui_ops ( gaim_gtk_debug_get_ui_ops ()); /* Set the UI operation structures. */ gaim_accounts_set_ui_ops ( gaim_gtk_accounts_get_ui_ops ()); gaim_conversations_set_win_ui_ops ( gaim_gtk_conversations_get_win_ui_ops ()); gaim_xfers_set_ui_ops ( gaim_gtk_xfers_get_ui_ops ()); gaim_blist_set_ui_ops ( gaim_gtk_blist_get_ui_ops ()); gaim_notify_set_ui_ops ( gaim_gtk_notify_get_ui_ops ()); gaim_privacy_set_ui_ops ( gaim_gtk_privacy_get_ui_ops ()); gaim_request_set_ui_ops ( gaim_gtk_request_get_ui_ops ()); gaim_sound_set_ui_ops ( gaim_gtk_sound_get_ui_ops ()); gaim_connections_set_ui_ops ( gaim_gtk_connections_get_ui_ops ()); gaim_gtk_conversations_init (); gaim_gtk_roomlist_init (); /* YYY is there an XXX here? */ /* captain's log, stardate... */ /* LOG system_log(log_quit, NULL, NULL, OPT_LOG_BUDDY_SIGNON | OPT_LOG_MY_SIGNON); */ /* Save the plugins we have loaded for next time. */ static GaimCoreUiOps core_ops = gaim_gtk_core_get_ui_ops ( void ) show_usage ( int mode , const char * name ) case 0 : /* full help text */ text = g_strdup_printf ( _ ( "Gaim %s \n " "Usage: %s [OPTION]... \n\n " " -a, --acct display account editor window \n " " -w, --away[=MESG] make away on signon (optional argument MESG specifies \n " " name of away message to use) \n " " -l, --login[=NAME] automatically login (optional argument NAME specifies \n " " account(s) to use, seperated by commas) \n " " -n, --loginwin don't automatically login; show login window \n " " -u, --user=NAME use account NAME \n " " -c, --config=DIR use DIR for config files \n " " -d, --debug print debugging messages to stdout \n " " -v, --version display the current version and exit \n " " -h, --help display this help and exit \n " ), VERSION , name ); case 1 : /* short message */ text = g_strdup_printf ( _ ( "Gaim %s. Try `%s -h' for more information. \n " ), VERSION , name ); /* tries to convert 'text' to users locale */ text_conv = g_locale_from_utf8 ( text , -1 , NULL , NULL , & error ); /* use 'text' as a fallback */ g_warning ( "%s \n " , error -> message ); #ifdef HAVE_STARTUP_NOTIFICATION sn_error_trap_push ( SnDisplay * display , Display * xdisplay ) sn_error_trap_pop ( SnDisplay * display , Display * xdisplay ) startup_notification_complete ( void ) xdisplay = GDK_DISPLAY (); sn_display = sn_display_new ( xdisplay , sn_launchee_context_new_from_environment ( sn_display , DefaultScreen ( xdisplay )); sn_launchee_context_complete ( sn_context ); sn_launchee_context_unref ( sn_context ); sn_display_unref ( sn_display ); #endif /* HAVE_STARTUP_NOTIFICATION */ static char * gaim_find_binary_location ( void * symbol , void * data ) static char * fullname = NULL ; static gboolean first = TRUE ; char * basebuf , * linkbuf , * fullbuf ; /* We've already been through this. */ basebuf = g_find_program_in_path ( argv0 ); /* But we still need to deal with symbolic links */ while (( st . st_mode & S_IFLNK ) == S_IFLNK ) { linkbuf = g_malloc ( 1024 ); readlink ( basebuf , linkbuf , 1024 ); if ( linkbuf [ 0 ] == G_DIR_SEPARATOR ) { fullbuf = g_strdup ( linkbuf ); char * dirbuf = g_path_get_dirname ( basebuf ); fullbuf = g_strdup_printf ( "%s%s%s" , dirbuf , G_DIR_SEPARATOR_S , /* There's no memory leak here. Really! */ #endif /* #ifndef _WIN32 */ /* FUCKING GET ME A TOWEL! */ int gaim_main ( HINSTANCE hint , int argc , char * argv []) int main ( int argc , char * argv []) int opt_acct = 0 , opt_help = 0 , opt_version = 0 , opt_login = 0 , opt_nologin = 0 , dologin_ret = -1 ; char * opt_user_arg = NULL , * opt_login_arg = NULL ; char * opt_session_arg = NULL , * opt_config_dir_arg = NULL ; char * plugin_search_paths [ 3 ]; int sig_indx ; /* for setting up signal catching */ gchar * gaimrc , * accountsxml ; struct option long_options [] = { { "acct" , no_argument , NULL , 'a' }, /*{"away", optional_argument, NULL, 'w'}, */ { "help" , no_argument , NULL , 'h' }, /*{"login", optional_argument, NULL, 'l'}, */ { "loginwin" , no_argument , NULL , 'n' }, { "user" , required_argument , NULL , 'u' }, { "config" , required_argument , NULL , 'c' }, { "debug" , no_argument , NULL , 'd' }, { "version" , no_argument , NULL , 'v' }, { "session" , required_argument , NULL , 's' }, br_set_locate_fallback_func ( gaim_find_binary_location , argv [ 0 ]); bindtextdomain ( PACKAGE , LOCALEDIR ); bind_textdomain_codeset ( PACKAGE , "UTF-8" ); /* Let's not violate any PLA's!!!! */ /* jseymour: whatever the fsck that means */ /* Robot101: for some reason things like gdm like to block * * useful signals like SIGCHLD, so we unblock all the ones we * * declare a handler for. thanks JSeymour and Vann. */ if ( sigemptyset ( & sigset )) { snprintf ( errmsg , BUFSIZ , "Warning: couldn't initialise empty signal set" ); for ( sig_indx = 0 ; catch_sig_list [ sig_indx ] != -1 ; ++ sig_indx ) { if (( prev_sig_disp = signal ( catch_sig_list [ sig_indx ], sighandler )) == SIG_ERR ) { snprintf ( errmsg , BUFSIZ , "Warning: couldn't set signal %d for catching" , catch_sig_list [ sig_indx ]); if ( sigaddset ( & sigset , catch_sig_list [ sig_indx ])) { snprintf ( errmsg , BUFSIZ , "Warning: couldn't include signal %d for unblocking" , catch_sig_list [ sig_indx ]); for ( sig_indx = 0 ; ignore_sig_list [ sig_indx ] != -1 ; ++ sig_indx ) { if (( prev_sig_disp = signal ( ignore_sig_list [ sig_indx ], SIG_IGN )) == SIG_ERR ) { snprintf ( errmsg , BUFSIZ , "Warning: couldn't set signal %d to ignore" , ignore_sig_list [ sig_indx ]); if ( sigprocmask ( SIG_UNBLOCK , & sigset , NULL )) { snprintf ( errmsg , BUFSIZ , "Warning: couldn't unblock signals" ); for ( i = 0 ; i < argc ; i ++ ) { if ( strstr ( argv [ i ], "--l" ) == argv [ i ]) { if (( equals = strchr ( argv [ i ], '=' )) != NULL ) { opt_login_arg = g_strdup ( equals + 1 ); if ( strlen ( opt_login_arg ) == 0 ) { } else if ( i + 1 < argc && argv [ i + 1 ][ 0 ] != '-' ) { opt_login_arg = g_strdup ( argv [ i + 1 ]); strcpy ( argv [ i + 1 ], " " ); else if ( strstr ( argv [ i ], "-l" ) == argv [ i ]) { if ( strlen ( argv [ i ]) > 2 ) { opt_login_arg = g_strdup ( argv [ i ] + 2 ); } else if ( i + 1 < argc && argv [ i + 1 ][ 0 ] != '-' ) { opt_login_arg = g_strdup ( argv [ i + 1 ]); strcpy ( argv [ i + 1 ], " " ); else if ( strstr ( argv [ i ], "--aw" ) == argv [ i ]) { if (( equals = strchr ( argv [ i ], '=' )) != NULL ) { opt_away_arg = g_strdup ( equals + 1 ); if ( strlen ( opt_away_arg ) == 0 ) { } else if ( i + 1 < argc && argv [ i + 1 ][ 0 ] != '-' ) { opt_away_arg = g_strdup ( argv [ i + 1 ]); strcpy ( argv [ i + 1 ], " " ); else if ( strstr ( argv [ i ], "-w" ) == argv [ i ]) { if ( strlen ( argv [ i ]) > 2 ) { opt_away_arg = g_strdup ( argv [ i ] + 2 ); } else if ( i + 1 < argc && argv [ i + 1 ][ 0 ] != '-' ) { opt_away_arg = g_strdup ( argv [ i + 1 ]); strcpy ( argv [ i + 1 ], " " ); printf ("--login given with arg %s\n", opt_login_arg ? opt_login_arg : "NULL"); gui_check = gtk_init_check ( & argc , & argv ); /* scan command-line options */ while (( opt = getopt_long ( argc , argv , long_options , NULL )) != -1 ) { opt_user_arg = g_strdup ( optarg ); case 'a' : /* account editor */ case 'c' : /* use specified config dir */ set_gaim_user_dir ( optarg ); opt_config_dir_arg = g_strdup ( optarg ); case 's' : /* use existing session ID */ opt_session_arg = g_strdup ( optarg ); case 'n' : /* don't autologin */ /* show version message */ printf ( "Gaim %s \n " , VERSION ); char * display = gdk_get_display (); g_warning ( "cannot open display: %s" , display ? display : "unset" ); gaim_core_set_ui_ops ( gaim_gtk_core_get_ui_ops ()); gaim_eventloop_set_ui_ops ( gaim_gtk_eventloop_get_ui_ops ()); if ( ! gaim_core_init ( GAIM_GTK_UI )) { "Initialization of the Gaim core failed. Dumping core. \n " "Please report this! \n " ); plugin_search_paths [ 0 ] = g_strdup ( LIBDIR ); plugin_search_paths [ 1 ] = gaim_user_dir (); plugin_search_paths [ 2 ] = g_build_filename ( gaim_user_dir (), "plugins" , NULL ); gaim_plugins_set_search_paths ( sizeof ( plugin_search_paths ) / sizeof ( * plugin_search_paths ), g_free ( plugin_search_paths [ 0 ]); g_free ( plugin_search_paths [ 2 ]); gaim_plugins_probe ( NULL ); /* XXX - Remove this check. Maybe in 2005. --KingAnt, 25 Jul 2004 */ gaimrc = g_build_filename ( gaim_home_dir (), ".gaimrc" , NULL ); accountsxml = g_build_filename ( gaim_user_dir (), "accounts.xml" , NULL ); if ( g_file_test ( gaimrc , G_FILE_TEST_EXISTS ) && ! g_file_test ( accountsxml , G_FILE_TEST_EXISTS )) { 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." )); gaim_set_blist ( gaim_blist_new ()); gaim_gtk_prefs_update_old (); /* load plugins we had when we quit */ gaim_plugins_load_saved ( "/gaim/gtk/plugins/loaded" ); session_init ( argv [ 0 ], opt_session_arg , opt_config_dir_arg ); if ( opt_session_arg != NULL ) { if ( opt_config_dir_arg != NULL ) { g_free ( opt_config_dir_arg ); opt_config_dir_arg = NULL ; /* set the default username */ if ( opt_user_arg != NULL ) { set_first_user ( opt_user_arg ); if ( gaim_prefs_get_bool ( "/gaim/gtk/debug/enabled" )) gaim_gtk_debug_window_show (); dologin_ret = dologin_named ( opt_login_arg ); if ( opt_login_arg != NULL ) { if ( ! opt_acct && ! opt_nologin ) gaim_accounts_auto_login ( GAIM_GTK_UI ); gaim_gtk_accounts_window_show (); } else if (( dologin_ret == -1 ) && ! gaim_connections_get_all ()) #ifdef HAVE_STARTUP_NOTIFICATION startup_notification_complete ();