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     "3.5-filter-icons",
00118     "3.5.4"
00119   };
00120   static const int numUpdates = sizeof updates / sizeof *updates;
00121   // Warning: do not remove entries in the above array, or the update-level check below will break
00122 
00123   KConfig * config = KMKernel::config();
00124   KConfigGroup startup( config, "Startup" );
00125   const int configUpdateLevel = startup.readNumEntry( "update-level", 0 );
00126   if ( configUpdateLevel == numUpdates ) // Optimize for the common case that everything is OK
00127     return;
00128 
00129   for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
00130     config->checkUpdate( updates[i], "kmail.upd" );
00131   }
00132   startup.writeEntry( "update-level", numUpdates );
00133 }
00134 
00135 void lockOrDie() {
00136 // Check and create a lock file to prevent concurrent access to kmail files
00137   QString appName = kapp->instanceName();
00138   if ( appName.isEmpty() )
00139     appName = "kmail";
00140 
00141   QString programName;
00142   const KAboutData *about = kapp->aboutData();
00143   if ( about )
00144     programName = about->programName();
00145   if ( programName.isEmpty() )
00146     programName = i18n("KMail");
00147 
00148   QString lockLocation = locateLocal("data", "kmail/lock");
00149   KSimpleConfig config(lockLocation);
00150   int oldPid = config.readNumEntry("pid", -1);
00151   const QString oldHostName = config.readEntry("hostname");
00152   const QString oldAppName = config.readEntry( "appName", appName );
00153   const QString oldProgramName = config.readEntry( "programName", programName );
00154   const QString hostName = getMyHostName();
00155   bool first_instance = false;
00156   if ( oldPid == -1 )
00157       first_instance = true;
00158   // check if the lock file is stale by trying to see if
00159   // the other pid is currently running.
00160   // Not 100% correct but better safe than sorry
00161   else if (hostName == oldHostName && oldPid != getpid()) {
00162       if ( kill(oldPid, 0) == -1 )
00163           first_instance = ( errno == ESRCH );
00164   }
00165 
00166   if ( !first_instance ) {
00167     QString msg;
00168     if ( oldHostName == hostName ) {
00169       // this can only happen if the user is running this application on
00170       // different displays on the same machine. All other cases will be
00171       // taken care of by KUniqueApplication()
00172       if ( oldAppName == appName )
00173         msg = i18n("%1 already seems to be running on another display on "
00174                    "this machine. Running %2 more than once "
00175                    "can cause the loss of mail. You should not start %1 "
00176                    "unless you are sure that it is not already running.")
00177               .arg( programName, programName );
00178               // QString::arg( st ) only replaces the first occurrence of %1
00179               // with st while QString::arg( s1, s2 ) replacess all occurrences
00180               // of %1 with s1 and all occurrences of %2 with s2. So don't
00181               // even think about changing the above to .arg( programName ).
00182       else
00183         msg = i18n("%1 seems to be running on another display on this "
00184                    "machine. Running %1 and %2 at the same "
00185                    "time can cause the loss of mail. You should not start %2 "
00186                    "unless you are sure that %1 is not running.")
00187               .arg( oldProgramName, programName );
00188     }
00189     else {
00190       if ( oldAppName == appName )
00191         msg = i18n("%1 already seems to be running on %2. Running %1 more "
00192                    "than once can cause the loss of mail. You should not "
00193                    "start %1 on this computer unless you are sure that it is "
00194                    "not already running on %2.")
00195               .arg( programName, oldHostName );
00196       else
00197         msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
00198                    "same time can cause the loss of mail. You should not "
00199                    "start %2 on this computer unless you are sure that %1 is "
00200                    "not running on %3.")
00201               .arg( oldProgramName, programName, oldHostName );
00202     }
00203 
00204     KCursorSaver idle( KBusyPtr::idle() );
00205     if ( KMessageBox::No ==
00206          KMessageBox::warningYesNo( 0, msg, QString::null,
00207                                     i18n("Start %1").arg( programName ),
00208                                     i18n("Exit") ) ) {
00209       exit(1);
00210     }
00211   }
00212 
00213   config.writeEntry("pid", getpid());
00214   config.writeEntry("hostname", hostName);
00215   config.writeEntry( "appName", appName );
00216   config.writeEntry( "programName", programName );
00217   config.sync();
00218 }
00219 
00220 void insertLibraryCataloguesAndIcons() {
00221   static const char * const catalogues[] = {
00222     "libkdepim",
00223     "libksieve",
00224     "libkleopatra",
00225     "libkmime"
00226   };
00227 
00228   KLocale * l = KGlobal::locale();
00229   KIconLoader * il = KGlobal::iconLoader();
00230   for ( unsigned int i = 0 ; i < sizeof catalogues / sizeof *catalogues ; ++i ) {
00231     l->insertCatalogue( catalogues[i] );
00232     il->addAppDir( catalogues[i] );
00233   }
00234 
00235 }
00236 
00237 void cleanup()
00238 {
00239   const QString lockLocation = locateLocal("data", "kmail/lock");
00240   KSimpleConfig config(lockLocation);
00241   config.writeEntry("pid", -1);
00242   config.sync();
00243 }
00244 }
KDE Home | KDE Accessibility Home | Description of Access Keys