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-filter-icons",
00120 "3.5.4",
00121 "3.5.7-imap-flag-migration"
00122 };
00123 static const int numUpdates = sizeof updates / sizeof *updates;
00124
00125
00126 KConfig * config = KMKernel::config();
00127 KConfigGroup startup( config, "Startup" );
00128 const int configUpdateLevel = startup.readNumEntry( "update-level", 0 );
00129 if ( configUpdateLevel == numUpdates )
00130 return;
00131
00132 for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
00133 config->checkUpdate( updates[i], "kmail.upd" );
00134 }
00135 startup.writeEntry( "update-level", numUpdates );
00136 }
00137
00138 void lockOrDie() {
00139
00140 QString appName = kapp->instanceName();
00141 if ( appName.isEmpty() )
00142 appName = "kmail";
00143
00144 QString programName;
00145 const KAboutData *about = kapp->aboutData();
00146 if ( about )
00147 programName = about->programName();
00148 if ( programName.isEmpty() )
00149 programName = i18n("KMail");
00150
00151 QString lockLocation = locateLocal("data", "kmail/lock");
00152 KSimpleConfig config(lockLocation);
00153 int oldPid = config.readNumEntry("pid", -1);
00154 const QString oldHostName = config.readEntry("hostname");
00155 const QString oldAppName = config.readEntry( "appName", appName );
00156 const QString oldProgramName = config.readEntry( "programName", programName );
00157 const QString hostName = getMyHostName();
00158 bool first_instance = false;
00159 if ( oldPid == -1 )
00160 first_instance = true;
00161 else if (hostName == oldHostName && oldPid != getpid()) {
00162
00163 #ifdef Q_OS_LINUX
00164 if ( ::access("/proc", X_OK ) == 0 ) {
00165
00166 char path_buffer[MAXPATHLEN + 1];
00167 path_buffer[MAXPATHLEN] = 0;
00168 const QString procPath = QString("/proc/%1/exe").arg(oldPid);
00169 const int length = readlink (procPath.latin1(), path_buffer, MAXPATHLEN);
00170 if ( length == -1 )
00171 first_instance = true;
00172 else {
00173 path_buffer[length] = '\0';
00174 const QString path = QFile::decodeName(path_buffer);
00175 kdDebug() << k_funcinfo << path << endl;
00176 const int pos = path.findRev('/');
00177 const QString fileName = path.mid(pos+1);
00178 kdDebug() << "Found process " << oldPid << " running. It's: " << fileName << endl;
00179 first_instance = fileName != "kmail" && fileName != "kontact";
00180 }
00181 } else
00182 #endif
00183 {
00184
00185
00186 if ( kill(oldPid, 0) == -1 )
00187 first_instance = ( errno == ESRCH );
00188 }
00189 }
00190
00191 if ( !first_instance ) {
00192 QString msg;
00193 if ( oldHostName == hostName ) {
00194
00195
00196
00197 if ( oldAppName == appName )
00198 msg = i18n("%1 already seems to be running on another display on "
00199 "this machine. Running %2 more than once "
00200 "can cause the loss of mail. You should not start %1 "
00201 "unless you are sure that it is not already running.")
00202 .arg( programName, programName );
00203
00204
00205
00206
00207 else
00208 msg = i18n("%1 seems to be running on another display on this "
00209 "machine. Running %1 and %2 at the same "
00210 "time can cause the loss of mail. You should not start %2 "
00211 "unless you are sure that %1 is not running.")
00212 .arg( oldProgramName, programName );
00213 }
00214 else {
00215 if ( oldAppName == appName )
00216 msg = i18n("%1 already seems to be running on %2. Running %1 more "
00217 "than once can cause the loss of mail. You should not "
00218 "start %1 on this computer unless you are sure that it is "
00219 "not already running on %2.")
00220 .arg( programName, oldHostName );
00221 else
00222 msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
00223 "same time can cause the loss of mail. You should not "
00224 "start %2 on this computer unless you are sure that %1 is "
00225 "not running on %3.")
00226 .arg( oldProgramName, programName, oldHostName );
00227 }
00228
00229 KCursorSaver idle( KBusyPtr::idle() );
00230 if ( KMessageBox::No ==
00231 KMessageBox::warningYesNo( 0, msg, QString::null,
00232 i18n("Start %1").arg( programName ),
00233 i18n("Exit") ) ) {
00234 exit(1);
00235 }
00236 }
00237
00238 config.writeEntry("pid", getpid());
00239 config.writeEntry("hostname", hostName);
00240 config.writeEntry( "appName", appName );
00241 config.writeEntry( "programName", programName );
00242 config.sync();
00243 }
00244
00245 void insertLibraryCataloguesAndIcons() {
00246 static const char * const catalogues[] = {
00247 "libkdepim",
00248 "libksieve",
00249 "libkleopatra",
00250 "libkmime"
00251 };
00252
00253 KLocale * l = KGlobal::locale();
00254 KIconLoader * il = KGlobal::iconLoader();
00255 for ( unsigned int i = 0 ; i < sizeof catalogues / sizeof *catalogues ; ++i ) {
00256 l->insertCatalogue( catalogues[i] );
00257 il->addAppDir( catalogues[i] );
00258 }
00259
00260 }
00261
00262 void cleanup()
00263 {
00264 const QString lockLocation = locateLocal("data", "kmail/lock");
00265 KSimpleConfig config(lockLocation);
00266 config.writeEntry("pid", -1);
00267 config.sync();
00268 }
00269 }