00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <config.h>
00020
00021 #include "kmstartup.h"
00022
00023 #include "kmkernel.h"
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 <sys/param.h>
00040 #include <signal.h>
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <unistd.h>
00044 #include <qfile.h>
00045
00046 #undef Status // stupid X headers
00047
00048 extern "C" {
00049
00050
00051 void kmsignalHandler(int sigId)
00052 {
00053 kmsetSignalHandler(SIG_DFL);
00054 fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
00055
00056 if (kmkernel) kmkernel->dumpDeadLetters();
00057 ::exit(-1);
00058 }
00059
00060
00061 void kmcrashHandler(int sigId)
00062 {
00063 kmsetSignalHandler(SIG_DFL);
00064 fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
00065
00066 if (kmkernel) kmkernel->dumpDeadLetters();
00067
00068 }
00069
00070
00071
00072 void kmsetSignalHandler(void (*handler)(int))
00073 {
00074 signal(SIGKILL, handler);
00075 signal(SIGTERM, handler);
00076 signal(SIGHUP, handler);
00077 KCrash::setEmergencySaveFunction(kmcrashHandler);
00078 }
00079
00080 }
00081
00082
00083 namespace {
00084 QString getMyHostName() {
00085 char hostNameC[256];
00086
00087 hostNameC[255] = 0;
00088
00089 if(gethostname(hostNameC, 255))
00090 hostNameC[0] = 0;
00091 return QString::fromLocal8Bit(hostNameC);
00092 }
00093 }
00094
00095 namespace KMail {
00096
00097 void checkConfigUpdates() {
00098 static const char * const updates[] = {
00099 "9",
00100 "3.1-update-identities",
00101 "3.1-use-identity-uoids",
00102 "3.1-new-mail-notification",
00103 "3.2-update-loop-on-goto-unread-settings",
00104 "3.1.4-dont-use-UOID-0-for-any-identity",
00105 "3.2-misc",
00106 "3.2-moves",
00107 "3.3-use-ID-for-accounts",
00108 "3.3-update-filter-rules",
00109 "3.3-move-identities-to-own-file",
00110 "3.3-aegypten-kpgprc-to-kmailrc",
00111 "3.3-aegypten-kpgprc-to-libkleopatrarc",
00112 "3.3-aegypten-emailidentities-split-sign-encr-keys",
00113 "3.3-misc",
00114 "3.3b1-misc",
00115 "3.4-misc",
00116 "3.4a",
00117 "3.4b",
00118 "3.4.1",
00119 "3.5.4",
00120 "3.5.7-imap-flag-migration"
00121 };
00122 static const int numUpdates = sizeof updates / sizeof *updates;
00123
00124
00125 KConfig * config = KMKernel::config();
00126 KConfigGroup startup( config, "Startup" );
00127 const int configUpdateLevel = startup.readNumEntry( "update-level", 0 );
00128 if ( configUpdateLevel == numUpdates )
00129 return;
00130
00131 for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
00132 config->checkUpdate( updates[i], "kmail.upd" );
00133 }
00134 startup.writeEntry( "update-level", numUpdates );
00135 }
00136
00137 void lockOrDie() {
00138
00139 QString appName = kapp->instanceName();
00140 if ( appName.isEmpty() )
00141 appName = "kmail";
00142
00143 QString programName;
00144 const KAboutData *about = kapp->aboutData();
00145 if ( about )
00146 programName = about->programName();
00147 if ( programName.isEmpty() )
00148 programName = i18n("KMail");
00149
00150 QString lockLocation = locateLocal("data", "kmail/lock");
00151 KSimpleConfig config(lockLocation);
00152 int oldPid = config.readNumEntry("pid", -1);
00153 const QString oldHostName = config.readEntry("hostname");
00154 const QString oldAppName = config.readEntry( "appName", appName );
00155 const QString oldProgramName = config.readEntry( "programName", programName );
00156 const QString hostName = getMyHostName();
00157 bool first_instance = false;
00158 if ( oldPid == -1 )
00159 first_instance = true;
00160 else if (hostName == oldHostName && oldPid != getpid()) {
00161
00162 #ifdef Q_OS_LINUX
00163 if ( ::access("/proc", X_OK ) == 0 ) {
00164
00165 char path_buffer[MAXPATHLEN + 1];
00166 path_buffer[MAXPATHLEN] = 0;
00167 const QString procPath = QString("/proc/%1/exe").arg(oldPid);
00168 const int length = readlink (procPath.latin1(), path_buffer, MAXPATHLEN);
00169 if ( length == -1 )
00170 first_instance = true;
00171 else {
00172 path_buffer[length] = '\0';
00173 const QString path = QFile::decodeName(path_buffer);
00174 kdDebug() << k_funcinfo << path << endl;
00175 const int pos = path.findRev('/');
00176 const QString fileName = path.mid(pos+1);
00177 kdDebug() << "Found process " << oldPid << " running. It's: " << fileName << endl;
00178 first_instance = fileName != "kmail" && fileName != "kontact";
00179 }
00180 } else
00181 #endif
00182 {
00183
00184
00185 if ( kill(oldPid, 0) == -1 )
00186 first_instance = ( errno == ESRCH );
00187 }
00188 }
00189
00190 if ( !first_instance ) {
00191 QString msg;
00192 if ( oldHostName == hostName ) {
00193
00194
00195
00196 if ( oldAppName == appName )
00197 msg = i18n("%1 already seems to be running on another display on "
00198 "this machine. Running %2 more than once "
00199 "can cause the loss of mail. You should not start %1 "
00200 "unless you are sure that it is not already running.")
00201 .arg( programName, programName );
00202
00203
00204
00205
00206 else
00207 msg = i18n("%1 seems to be running on another display on this "
00208 "machine. Running %1 and %2 at the same "
00209 "time can cause the loss of mail. You should not start %2 "
00210 "unless you are sure that %1 is not running.")
00211 .arg( oldProgramName, programName );
00212 }
00213 else {
00214 if ( oldAppName == appName )
00215 msg = i18n("%1 already seems to be running on %2. Running %1 more "
00216 "than once can cause the loss of mail. You should not "
00217 "start %1 on this computer unless you are sure that it is "
00218 "not already running on %2.")
00219 .arg( programName, oldHostName );
00220 else
00221 msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
00222 "same time can cause the loss of mail. You should not "
00223 "start %2 on this computer unless you are sure that %1 is "
00224 "not running on %3.")
00225 .arg( oldProgramName, programName, oldHostName );
00226 }
00227
00228 KCursorSaver idle( KBusyPtr::idle() );
00229 if ( KMessageBox::No ==
00230 KMessageBox::warningYesNo( 0, msg, QString::null,
00231 i18n("Start %1").arg( programName ),
00232 i18n("Exit") ) ) {
00233 exit(1);
00234 }
00235 }
00236
00237 config.writeEntry("pid", getpid());
00238 config.writeEntry("hostname", hostName);
00239 config.writeEntry( "appName", appName );
00240 config.writeEntry( "programName", programName );
00241 config.sync();
00242 }
00243
00244 void insertLibraryCataloguesAndIcons() {
00245 static const char * const catalogues[] = {
00246 "libkdepim",
00247 "libksieve",
00248 "libkleopatra",
00249 "libkmime"
00250 };
00251
00252 KLocale * l = KGlobal::locale();
00253 KIconLoader * il = KGlobal::iconLoader();
00254 for ( unsigned int i = 0 ; i < sizeof catalogues / sizeof *catalogues ; ++i ) {
00255 l->insertCatalogue( catalogues[i] );
00256 il->addAppDir( catalogues[i] );
00257 }
00258
00259 }
00260
00261 void cleanup()
00262 {
00263 const QString lockLocation = locateLocal("data", "kmail/lock");
00264 KSimpleConfig config(lockLocation);
00265 config.writeEntry("pid", -1);
00266 config.sync();
00267 }
00268 }