kmail

kmstartup.cpp

00001 /*
00002     This file is part of KMail, the KDE mail client.
00003     Copyright (c) 2000 Don Sanders <sanders@kde.org>
00004 
00005     KMail is free software; you can redistribute it and/or modify it
00006     under the terms of the GNU General Public License, version 2, as
00007     published by the Free Software Foundation.
00008 
00009     KMail is distributed in the hope that it will be useful, but
00010     WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00017 */
00018 
00019 #include <config.h>
00020 
00021 #include "kmstartup.h"
00022 
00023 #include "kmkernel.h" //control center
00024 #include "kcursorsaver.h"
00025 
00026 #include <klocale.h>
00027 #include <ksimpleconfig.h>
00028 #include <kstandarddirs.h>
00029 #include <kmessagebox.h>
00030 #include <dcopclient.h>
00031 #include <kcrash.h>
00032 #include <kglobal.h>
00033 #include <kapplication.h>
00034 #include <kaboutdata.h>
00035 #include <kiconloader.h>
00036 
00037 #include <errno.h>
00038 #include <sys/types.h>
00039 #include <signal.h>
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <unistd.h>
00043 
00044 #undef Status // stupid X headers
00045 
00046 extern "C" {
00047 
00048 // Crash recovery signal handler
00049 void kmsignalHandler(int sigId)
00050 {
00051   kmsetSignalHandler(SIG_DFL);
00052   fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
00053   // try to cleanup all windows
00054   if (kmkernel) kmkernel->dumpDeadLetters();
00055   ::exit(-1); //
00056 }
00057 
00058 // Crash recovery signal handler
00059 void kmcrashHandler(int sigId)
00060 {
00061   kmsetSignalHandler(SIG_DFL);
00062   fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
00063   // try to cleanup all windows
00064   if (kmkernel) kmkernel->dumpDeadLetters();
00065   // Return to DrKonqi.
00066 }
00067 //-----------------------------------------------------------------------------
00068 
00069 
00070 void kmsetSignalHandler(void (*handler)(int))
00071 {
00072   signal(SIGKILL, handler);
00073   signal(SIGTERM, handler);
00074   signal(SIGHUP,  handler);
00075   KCrash::setEmergencySaveFunction(kmcrashHandler);
00076 }
00077 
00078 }
00079 //-----------------------------------------------------------------------------
00080 
00081 namespace {
00082   QString getMyHostName() {
00083     char hostNameC[256];
00084     // null terminate this C string
00085     hostNameC[255] = 0;
00086     // set the string to 0 length if gethostname fails
00087     if(gethostname(hostNameC, 255))
00088       hostNameC[0] = 0;
00089     return QString::fromLocal8Bit(hostNameC);
00090   }
00091 } // anon namespace
00092 
00093 namespace KMail {
00094 
00095 void checkConfigUpdates() {
00096   static const char * const updates[] = {
00097     "9",
00098     "3.1-update-identities",
00099     "3.1-use-identity-uoids",
00100     "3.1-new-mail-notification",
00101     "3.2-update-loop-on-goto-unread-settings",
00102     "3.1.4-dont-use-UOID-0-for-any-identity",
00103     "3.2-misc",
00104     "3.2-moves",
00105     "3.3-use-ID-for-accounts",
00106     "3.3-update-filter-rules",
00107     "3.3-move-identities-to-own-file",
00108     "3.3-aegypten-kpgprc-to-kmailrc",
00109     "3.3-aegypten-kpgprc-to-libkleopatrarc",
00110     "3.3-aegypten-emailidentities-split-sign-encr-keys",
00111     "3.3-misc",
00112     "3.3b1-misc",
00113     "3.4-misc",
00114     "3.4a",
00115     "3.4b",
00116     "3.4.1"
00117   };
00118   static const int numUpdates = sizeof updates / sizeof *updates;
00119   // Warning: do not remove entries in the above array, or the update-level check below will break
00120 
00121   KConfig * config = KMKernel::config();
00122   KConfigGroup startup( config, "Startup" );
00123   const int configUpdateLevel = startup.readNumEntry( "update-level", 0 );
00124   if ( configUpdateLevel == numUpdates ) // Optimize for the common case that everything is OK
00125     return;
00126 
00127   for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
00128     config->checkUpdate( updates[i], "kmail.upd" );
00129   }
00130   startup.writeEntry( "update-level", numUpdates );
00131 }
00132 
00133 void lockOrDie() {
00134 // Check and create a lock file to prevent concurrent access to kmail files
00135   QString appName = kapp->instanceName();
00136   if ( appName.isEmpty() )
00137     appName = "kmail";
00138 
00139   QString programName;
00140   const KAboutData *about = kapp->aboutData();
00141   if ( about )
00142     programName = about->programName();
00143   if ( programName.isEmpty() )
00144     programName = i18n("KMail");
00145 
00146   QString lockLocation = locateLocal("data", "kmail/lock");
00147   KSimpleConfig config(lockLocation);
00148   int oldPid = config.readNumEntry("pid", -1);
00149   const QString oldHostName = config.readEntry("hostname");
00150   const QString oldAppName = config.readEntry( "appName", appName );
00151   const QString oldProgramName = config.readEntry( "programName", programName );
00152   const QString hostName = getMyHostName();
00153   bool first_instance = false;
00154   if ( oldPid == -1 )
00155       first_instance = true;
00156   // check if the lock file is stale by trying to see if
00157   // the other pid is currently running.
00158   // Not 100% correct but better safe than sorry
00159   else if (hostName == oldHostName && oldPid != getpid()) {
00160       if ( kill(oldPid, 0) == -1 )
00161           first_instance = ( errno == ESRCH );
00162   }
00163 
00164   if ( !first_instance ) {
00165     QString msg;
00166     if ( oldHostName == hostName ) {
00167       // this can only happen if the user is running this application on
00168       // different displays on the same machine. All other cases will be
00169       // taken care of by KUniqueApplication()
00170       if ( oldAppName == appName )
00171         msg = i18n("%1 already seems to be running on another display on "
00172                    "this machine. Running %2 more than once "
00173                    "can cause the loss of mail. You should not start %1 "
00174                    "unless you are sure that it is not already running.")
00175               .arg( programName, programName );
00176               // QString::arg( st ) only replaces the first occurrence of %1
00177               // with st while QString::arg( s1, s2 ) replacess all occurrences
00178               // of %1 with s1 and all occurrences of %2 with s2. So don't
00179               // even think about changing the above to .arg( programName ).
00180       else
00181         msg = i18n("%1 seems to be running on another display on this "
00182                    "machine. Running %1 and %2 at the same "
00183                    "time can cause the loss of mail. You should not start %2 "
00184                    "unless you are sure that %1 is not running.")
00185               .arg( oldProgramName, programName );
00186     }
00187     else {
00188       if ( oldAppName == appName )
00189         msg = i18n("%1 already seems to be running on %2. Running %1 more "
00190                    "than once can cause the loss of mail. You should not "
00191                    "start %1 on this computer unless you are sure that it is "
00192                    "not already running on %2.")
00193               .arg( programName, oldHostName );
00194       else
00195         msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
00196                    "same time can cause the loss of mail. You should not "
00197                    "start %2 on this computer unless you are sure that %1 is "
00198                    "not running on %3.")
00199               .arg( oldProgramName, programName, oldHostName );
00200     }
00201 
00202     KCursorSaver idle( KBusyPtr::idle() );
00203     if ( KMessageBox::No ==
00204          KMessageBox::warningYesNo( 0, msg, QString::null,
00205                                     i18n("Start %1").arg( programName ),
00206                                     i18n("Exit") ) ) {
00207       exit(1);
00208     }
00209   }
00210 
00211   config.writeEntry("pid", getpid());
00212   config.writeEntry("hostname", hostName);
00213   config.writeEntry( "appName", appName );
00214   config.writeEntry( "programName", programName );
00215   config.sync();
00216 }
00217 
00218 void insertLibraryCataloguesAndIcons() {
00219   static const char * const catalogues[] = {
00220     "libkdepim",
00221     "libksieve",
00222     "libkleopatra",
00223     "libkmime"
00224   };
00225 
00226   KLocale * l = KGlobal::locale();
00227   KIconLoader * il = KGlobal::iconLoader();
00228   for ( unsigned int i = 0 ; i < sizeof catalogues / sizeof *catalogues ; ++i ) {
00229     l->insertCatalogue( catalogues[i] );
00230     il->addAppDir( catalogues[i] );
00231   }
00232 
00233 }
00234 
00235 void cleanup()
00236 {
00237   const QString lockLocation = locateLocal("data", "kmail/lock");
00238   KSimpleConfig config(lockLocation);
00239   config.writeEntry("pid", -1);
00240   config.sync();
00241 }
00242 }
KDE Home | KDE Accessibility Home | Description of Access Keys