1 /***************************************************************************
2 * Copyright (C) 2005-08 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
24 #include <QTranslator>
31 #include "cliparser.h"
33 #if defined BUILD_CORE
38 #elif defined BUILD_QTUI
40 #include "qtuiapplication.h"
43 #elif defined BUILD_MONO
46 #include "coresession.h"
47 #include "qtuiapplication.h"
51 #error "Something is wrong - you need to #define a build mode!"
57 #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
63 //! Signal handler for graceful shutdown.
64 void handle_signal(int sig) {
65 qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig)));
66 QCoreApplication::quit();
69 #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
70 void handle_crash(int sig) {
73 int i, frames = backtrace(callstack, 128);
75 QFile dumpFile(QString("Quassel-Crash-%1").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm.log")));
76 dumpFile.open(QIODevice::WriteOnly);
77 QTextStream dumpStream(&dumpFile);
79 for (i = 0; i < frames; ++i) {
81 dladdr (callstack[i], &info);
85 // __const char *dli_fname; /* File name of defining object. */
86 // void *dli_fbase; /* Load address of that object. */
87 // __const char *dli_sname; /* Name of nearest symbol. */
88 // void *dli_saddr; /* Exact value of nearest symbol. */
99 char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0);
101 funcName = QString(func);
104 funcName = QString(info.dli_sname);
107 funcName = QString("0x%1").arg((long)info.dli_saddr, addrSize, QLatin1Char('0'));
110 // prettificating the filename
111 QString fileName("???");
113 fileName = QString(info.dli_fname);
114 int slashPos = fileName.lastIndexOf('/');
116 fileName = fileName.mid(slashPos + 1);
117 if(fileName.count() < 20)
118 fileName += QString(20 - fileName.count(), ' ');
121 QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10)
123 .arg((long)(callstack[i]), addrSize, 16, QLatin1Char('0'))
126 dumpStream << debugLine << "\n";
127 qDebug() << qPrintable(debugLine);
132 #endif // #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
135 int main(int argc, char **argv) {
136 // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel.
137 signal(SIGTERM, handle_signal);
138 signal(SIGINT, handle_signal);
140 #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
141 signal(SIGABRT, handle_crash);
142 signal(SIGBUS, handle_crash);
143 signal(SIGSEGV, handle_crash);
144 #endif // #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
146 Global::registerMetaTypes();
147 Global::setupVersion();
150 #if defined BUILD_CORE
151 Global::runMode = Global::CoreOnly;
152 QCoreApplication app(argc, argv);
153 #elif defined BUILD_QTUI
154 Global::runMode = Global::ClientOnly;
155 QApplication app(argc, argv);
157 Global::runMode = Global::Monolithic;
158 QApplication app(argc, argv);
161 #if defined BUILD_CORE
162 Global::runMode = Global::CoreOnly;
163 QCoreApplication app(argc, argv);
164 #elif defined BUILD_QTUI
165 Global::runMode = Global::ClientOnly;
166 QtUiApplication app(argc, argv);
168 Global::runMode = Global::Monolithic;
169 QtUiApplication app(argc, argv);
172 Global::parser = CliParser(QCoreApplication::arguments());
175 // put core-only arguments here
176 Global::parser.addOption("port",'p',"The port quasselcore will listen at",QString("4242"));
177 Global::parser.addSwitch("norestore", 'n', "Don't restore last core's state");
178 Global::parser.addOption("logfile",'l',"Path to logfile");
179 Global::parser.addOption("loglevel",'L',"Loglevel Debug|Info|Warning|Error","Info");
180 Global::parser.addOption("datadir", 0, "Specify the directory holding datafiles like the Sqlite DB and the SSL Cert");
183 // put client-only arguments here
184 Global::parser.addSwitch("debugbufferswitches",0,"Enables debugging for bufferswitches");
185 Global::parser.addSwitch("debugmodel",0,"Enables debugging for models");
186 #endif // BUILD_QTCORE
187 // put shared client&core arguments here
188 Global::parser.addSwitch("debug",'d',"Enable debug output");
189 Global::parser.addSwitch("help",'h', "Display this help and exit");
191 if(!Global::parser.parse() || Global::parser.isSet("help")) {
192 Global::parser.usage();
197 This is an initial check if logfile is writable since the warning would spam stdout if done
198 in current Logger implementation. Can be dropped whenever the logfile is only opened once.
200 if(Global::runMode != Global::ClientOnly) {
202 if(!Global::parser.value("logfile").isEmpty()) {
203 logFile.setFileName(Global::parser.value("logfile"));
204 if(!logFile.open(QIODevice::Append | QIODevice::Text))
205 qWarning("Warning: Couldn't open logfile '%s' - will log to stdout instead",qPrintable(logFile.fileName()));
206 else logFile.close();
210 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
212 // Set up i18n support
213 QLocale locale = QLocale::system();
215 QTranslator qtTranslator(&app);
216 qtTranslator.setObjectName("QtTr");
217 qtTranslator.load(QString(":i18n/qt_%1").arg(locale.name()));
218 app.installTranslator(&qtTranslator);
220 QTranslator quasselTranslator(&app);
221 quasselTranslator.setObjectName("QuasselTr");
222 quasselTranslator.load(QString(":i18n/quassel_%1").arg(locale.name()));
223 app.installTranslator(&quasselTranslator);
225 Network::setDefaultCodecForServer("ISO-8859-1");
226 Network::setDefaultCodecForEncoding("UTF-8");
227 Network::setDefaultCodecForDecoding("ISO-8859-15");
229 QCoreApplication::setOrganizationDomain("quassel-irc.org");
230 QCoreApplication::setApplicationName("Quassel IRC");
231 QCoreApplication::setOrganizationName("Quassel Project");
235 Core::instance(); // create and init the core
242 QtUi *gui = new QtUi();
244 // init gui only after the event loop has started
245 QTimer::singleShot(0, gui, SLOT(init()));
250 if(!Global::parser.isSet("norestore")) {
251 Core::restoreState();
256 app.resumeSessionIfPossible();
259 int exitCode = app.exec();
266 // the mainWin has to be deleted before the Core
267 // if not Quassel will crash on exit under certain conditions since the gui
268 // still wants to access clientdata