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