kmail

kmstartup.cpp
1/*
2 This file is part of KMail, the KDE mail client.
3 Copyright (c) 2000 Don Sanders <sanders@kde.org>
4
5 KMail is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License, version 2, as
7 published by the Free Software Foundation.
8
9 KMail is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include <config.h>
20
21#include "kmstartup.h"
22
23#include "kmkernel.h" //control center
24#include "kcursorsaver.h"
25
26#include <tdelocale.h>
27#include <ksimpleconfig.h>
28#include <tdestandarddirs.h>
29#include <tdemessagebox.h>
30#include <dcopclient.h>
31#include <tdecrash.h>
32#include <tdeglobal.h>
33#include <tdeapplication.h>
34#include <tdeaboutdata.h>
35#include <kiconloader.h>
36
37#include <errno.h>
38#include <sys/types.h>
39#include <sys/param.h>
40#include <signal.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <tqfile.h>
45
46#undef Status // stupid X headers
47
48extern "C" {
49
50// Crash recovery signal handler
51void kmsignalHandler(int sigId)
52{
53 kmsetSignalHandler(SIG_DFL);
54 fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
55 // try to cleanup all windows
56 if (kmkernel) kmkernel->dumpDeadLetters();
57 ::exit(-1); //
58}
59
60// Crash recovery signal handler
61void kmcrashHandler(int sigId)
62{
63 kmsetSignalHandler(SIG_DFL);
64 fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
65 // try to cleanup all windows
66 if (kmkernel) kmkernel->dumpDeadLetters();
67 // Return to DrKonqi.
68}
69//-----------------------------------------------------------------------------
70
71
72void kmsetSignalHandler(void (*handler)(int))
73{
74 signal(SIGKILL, handler);
75 signal(SIGTERM, handler);
76 signal(SIGHUP, handler);
77 TDECrash::setEmergencySaveFunction(kmcrashHandler);
78}
79
80}
81//-----------------------------------------------------------------------------
82
83namespace {
84 TQString getMyHostName() {
85 char hostNameC[256];
86 // null terminate this C string
87 hostNameC[255] = 0;
88 // set the string to 0 length if gethostname fails
89 if(gethostname(hostNameC, 255))
90 hostNameC[0] = 0;
91 return TQString::fromLocal8Bit(hostNameC);
92 }
93} // anon namespace
94
95namespace KMail {
96
97void checkConfigUpdates() {
98 static const char * const updates[] = {
99 "9",
100 "3.1-update-identities",
101 "3.1-use-identity-uoids",
102 "3.1-new-mail-notification",
103 "3.2-update-loop-on-goto-unread-settings",
104 "3.1.4-dont-use-UOID-0-for-any-identity",
105 "3.2-misc",
106 "3.2-moves",
107 "3.3-use-ID-for-accounts",
108 "3.3-update-filter-rules",
109 "3.3-move-identities-to-own-file",
110 "3.3-aegypten-kpgprc-to-kmailrc",
111 "3.3-aegypten-kpgprc-to-libkleopatrarc",
112 "3.3-aegypten-emailidentities-split-sign-encr-keys",
113 "3.3-misc",
114 "3.3b1-misc",
115 "3.4-misc",
116 "3.4a",
117 "3.4b",
118 "3.4.1",
119 "3.5-filter-icons",
120 "3.5.4",
121 "3.5.7-imap-flag-migration"
122 };
123 static const int numUpdates = sizeof updates / sizeof *updates;
124 // Warning: do not remove entries in the above array, or the update-level check below will break
125
126 TDEConfig * config = KMKernel::config();
127 TDEConfigGroup startup( config, "Startup" );
128 const int configUpdateLevel = startup.readNumEntry( "update-level", 0 );
129 if ( configUpdateLevel == numUpdates ) // Optimize for the common case that everything is OK
130 return;
131
132 for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
133 config->checkUpdate( updates[i], "kmail.upd" );
134 }
135 startup.writeEntry( "update-level", numUpdates );
136}
137
138void lockOrDie() {
139// Check and create a lock file to prevent concurrent access to kmail files
140 TQString appName = tdeApp->instanceName();
141 if ( appName.isEmpty() )
142 appName = "kmail";
143
144 TQString programName;
145 const TDEAboutData *about = tdeApp->aboutData();
146 if ( about )
147 programName = about->programName();
148 if ( programName.isEmpty() )
149 programName = i18n("KMail");
150
151 TQString lockLocation = locateLocal("data", "kmail/lock");
152 KSimpleConfig config(lockLocation);
153 int oldPid = config.readNumEntry("pid", -1);
154 const TQString oldHostName = config.readEntry("hostname");
155 const TQString oldAppName = config.readEntry( "appName", appName );
156 const TQString oldProgramName = config.readEntry( "programName", programName );
157 const TQString hostName = getMyHostName();
158 bool first_instance = false;
159 if ( oldPid == -1 )
160 first_instance = true;
161 else if (hostName == oldHostName && oldPid != getpid()) {
162 // check if the lock file is stale
163#ifdef TQ_OS_LINUX
164 if ( ::access("/proc", X_OK ) == 0 ) {
165 // On linux with /proc we can even check that it's really kmail and not something else
166 char path_buffer[MAXPATHLEN + 1];
167 path_buffer[MAXPATHLEN] = 0;
168 const TQString procPath = TQString("/proc/%1/exe").arg(oldPid);
169 const int length = readlink (procPath.latin1(), path_buffer, MAXPATHLEN);
170 if ( length == -1 ) // not such pid
171 first_instance = true;
172 else {
173 path_buffer[length] = '\0';
174 const TQString path = TQFile::decodeName(path_buffer);
175 kdDebug() << k_funcinfo << path << endl;
176 const int pos = path.findRev('/');
177 const TQString fileName = path.mid(pos+1);
178 kdDebug() << "Found process " << oldPid << " running. It's: " << fileName << endl;
179 first_instance = fileName != "kmail" && fileName != "kontact";
180 }
181 } else
182#endif
183 {
184 // Otherwise we just check if the other pid is currently running.
185 // Not 100% correct but better safe than sorry.
186 if ( kill(oldPid, 0) == -1 )
187 first_instance = ( errno == ESRCH );
188 }
189 }
190
191 if ( !first_instance ) {
192 TQString msg;
193 if ( oldHostName == hostName ) {
194 // this can only happen if the user is running this application on
195 // different displays on the same machine. All other cases will be
196 // taken care of by TDEUniqueApplication()
197 if ( oldAppName == appName )
198 msg = i18n("%1 already seems to be running on another display on "
199 "this machine. Running %2 more than once "
200 "can cause the loss of mail. You should not start %1 "
201 "unless you are sure that it is not already running.")
202 .arg( programName, programName );
203 // TQString::arg( st ) only replaces the first occurrence of %1
204 // with st while TQString::arg( s1, s2 ) replacess all occurrences
205 // of %1 with s1 and all occurrences of %2 with s2. So don't
206 // even think about changing the above to .arg( programName ).
207 else
208 msg = i18n("%1 seems to be running on another display on this "
209 "machine. Running %1 and %2 at the same "
210 "time can cause the loss of mail. You should not start %2 "
211 "unless you are sure that %1 is not running.")
212 .arg( oldProgramName, programName );
213 }
214 else {
215 if ( oldAppName == appName )
216 msg = i18n("%1 already seems to be running on %2. Running %1 more "
217 "than once can cause the loss of mail. You should not "
218 "start %1 on this computer unless you are sure that it is "
219 "not already running on %2.")
220 .arg( programName, oldHostName );
221 else
222 msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
223 "same time can cause the loss of mail. You should not "
224 "start %2 on this computer unless you are sure that %1 is "
225 "not running on %3.")
226 .arg( oldProgramName, programName, oldHostName );
227 }
228
229 KCursorSaver idle( KBusyPtr::idle() );
230 if ( KMessageBox::No ==
231 KMessageBox::warningYesNo( 0, msg, TQString(),
232 i18n("Start %1").arg( programName ),
233 i18n("Exit") ) ) {
234 exit(1);
235 }
236 }
237
238 config.writeEntry("pid", getpid());
239 config.writeEntry("hostname", hostName);
240 config.writeEntry( "appName", appName );
241 config.writeEntry( "programName", programName );
242 config.sync();
243}
244
245void insertLibraryCataloguesAndIcons() {
246 static const char * const catalogues[] = {
247 "libtdepim",
248 "libksieve",
249 "libkleopatra",
250 "libkmime"
251 };
252
253 TDELocale * l = TDEGlobal::locale();
254 TDEIconLoader * il = TDEGlobal::iconLoader();
255 for ( unsigned int i = 0 ; i < sizeof catalogues / sizeof *catalogues ; ++i ) {
256 l->insertCatalogue( catalogues[i] );
257 il->addAppDir( catalogues[i] );
258 }
259
260}
261
262void cleanup()
263{
264 const TQString lockLocation = locateLocal("data", "kmail/lock");
265 KSimpleConfig config(lockLocation);
266 config.writeEntry("pid", -1);
267 config.sync();
268}
269}
sets a cursor and makes sure it's restored on destruction Create a KCursorSaver object when you want ...
Definition: kcursorsaver.h:14
folderdiaquotatab.h
Definition: aboutdata.cpp:40