]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/receiver.cc
Cleanup of some code, adding of method to return current config.
[thirdparty/pdns.git] / pdns / receiver.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
bf6a52bf 3 Copyright (C) 2002 - 2011 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
22dc646a
BH
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
ea44d9d3 8
12c86877
BH
9
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.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
06bd9ccf 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877 18*/
e8d78143 19#include "packetcache.hh"
da44c9ea 20
12c86877
BH
21#include <cstdio>
22#include <signal.h>
23#include <cstring>
24#include <cstdlib>
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
29#include <iostream>
30#include <string>
31#include <sys/stat.h>
32#include <unistd.h>
33#include <sys/time.h>
34#include <sys/types.h>
35#include <sys/wait.h>
36#include <errno.h>
37#include <pthread.h>
38#include <unistd.h>
39#include <sys/mman.h>
40#include <fcntl.h>
41#include <fstream>
040712e0 42#include <boost/algorithm/string.hpp>
12c86877
BH
43
44#include "config.h"
45#include "dns.hh"
46#include "dnsbackend.hh"
47#include "ueberbackend.hh"
48#include "dnspacket.hh"
49#include "nameserver.hh"
50#include "distributor.hh"
51#include "logger.hh"
52#include "arguments.hh"
53#include "packethandler.hh"
54#include "statbag.hh"
55#include "tcpreceiver.hh"
12c86877
BH
56#include "ws.hh"
57#include "misc.hh"
58#include "dynlistener.hh"
59#include "dynhandler.hh"
60#include "communicator.hh"
61#include "dnsproxy.hh"
731f58b8 62#include "utility.hh"
12c86877 63#include "common_startup.hh"
02116dff 64#include "dnsrecords.hh"
12c86877 65
040712e0 66
12c86877
BH
67time_t s_starttime;
68
69string s_programname="pdns"; // used in packethandler.cc
70
c4ac5865 71const char *funnytext=
12c86877
BH
72"*****************************************************************************\n"\
73"Ok, you just ran pdns_server through 'strings' hoping to find funny messages.\n"\
74"Well, you found one. \n"\
75"Two ions are flying through their particle accelerator, says the one to the\n"
76"other 'I think I've lost an electron!' \n"\
77"So the other one says, 'Are you sure?'. 'YEAH! I'M POSITIVE!'\n"\
78" the pdns crew - pdns@powerdns.com\n"
79"*****************************************************************************\n";
80
81
82// start (sys)logging
83
84/** \var Logger L
85\brief All logging is done via L, a Logger instance
86*/
87
88
89/**
90\file receiver.cc
91\brief The main loop of powerdns
92
93This file is where it all happens - main is here, as are the two pivotal threads qthread() and athread()
94*/
95
96void daemonize(void)
97{
98 if(fork())
99 exit(0); // bye bye
100
101 setsid();
102
dd8b6bd1 103 int i=open("/dev/null",O_RDWR); /* open stdin */
11a2091b
BH
104 if(i < 0)
105 L<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
106 else {
107 dup2(i,0); /* stdin */
108 dup2(i,1); /* stderr */
109 dup2(i,2); /* stderr */
110 close(i);
111 }
12c86877
BH
112}
113
12c86877 114static int cpid;
12c86877
BH
115static void takedown(int i)
116{
117 if(cpid) {
118 L<<Logger::Error<<"Guardian is killed, taking down children with us"<<endl;
119 kill(cpid,SIGKILL);
93d8ebf9 120 exit(0);
12c86877
BH
121 }
122}
123
124static void writePid(void)
125{
e8d78143 126 string fname=::arg()["socket-dir"]+"/"+s_programname+".pid";
12c86877
BH
127 ofstream of(fname.c_str());
128 if(of)
129 of<<getpid()<<endl;
130 else
131 L<<Logger::Error<<"Requested to write pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl;
132}
133
aced0e6c
BH
134int g_fd1[2], g_fd2[2];
135FILE *g_fp;
136pthread_mutex_t g_guardian_lock = PTHREAD_MUTEX_INITIALIZER;
12c86877 137
64bcb6be
RA
138// The next two methods are not in dynhandler.cc because they use a few items declared in this file.
139static string DLCycleHandler(const vector<string>&parts, pid_t ppid)
140{
141 kill(cpid, SIGKILL); // why?
142 kill(cpid, SIGKILL); // why?
143 sleep(1);
144 return "ok";
145}
146
12c86877
BH
147static string DLRestHandler(const vector<string>&parts, pid_t ppid)
148{
149 string line;
150
151 for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i) {
152 if(i!=parts.begin())
153 line.append(1,' ');
154 line.append(*i);
155 }
156 line.append(1,'\n');
157
aced0e6c
BH
158 Lock l(&g_guardian_lock);
159
160 try {
161 writen2(g_fd1[1],line.c_str(),line.size()+1);
162 }
163 catch(AhuException &ae) {
164 return "Error communicating with instance: "+ae.reason;
165 }
12c86877 166 char mesg[512];
20ca8e7d 167 string response;
aced0e6c 168 while(fgets(mesg,sizeof(mesg),g_fp)) {
20ca8e7d
BH
169 if(*mesg=='\n')
170 break;
171 response+=mesg;
172 }
040712e0 173 boost::trim_right(response);
20ca8e7d 174 return response;
12c86877
BH
175}
176
64bcb6be 177
12c86877
BH
178
179static int guardian(int argc, char **argv)
180{
181 if(isGuarded(argv))
182 return 0;
183
184 int infd=0, outfd=1;
185
186 DynListener dlg(s_programname);
3c90953e
PD
187 dlg.registerFunc("QUIT",&DLQuitHandler, "quit daemon");
188 dlg.registerFunc("CYCLE",&DLCycleHandler, "restart instance");
189 dlg.registerFunc("PING",&DLPingHandler, "ping guardian");
190 dlg.registerFunc("STATUS",&DLStatusHandler, "get instance status from guardian");
12c86877
BH
191 dlg.registerRestFunc(&DLRestHandler);
192 dlg.go();
193 string progname=argv[0];
194
195 bool first=true;
196 cpid=0;
197
aced0e6c
BH
198 pthread_mutex_lock(&g_guardian_lock);
199
12c86877
BH
200 for(;;) {
201 int pid;
202 setStatus("Launching child");
aced0e6c
BH
203
204 if(pipe(g_fd1)<0 || pipe(g_fd2)<0) {
12c86877
BH
205 L<<Logger::Critical<<"Unable to open pipe for coprocess: "<<strerror(errno)<<endl;
206 exit(1);
207 }
208
aced0e6c
BH
209 if(!(g_fp=fdopen(g_fd2[0],"r"))) {
210 L<<Logger::Critical<<"Unable to associate a file pointer with pipe: "<<stringerror()<<endl;
211 exit(1);
212 }
213 setbuf(g_fp,0); // no buffering please, confuses select
214
12c86877
BH
215 if(!(pid=fork())) { // child
216 signal(SIGTERM, SIG_DFL);
217
218 signal(SIGHUP, SIG_DFL);
219 signal(SIGUSR1, SIG_DFL);
220 signal(SIGUSR2, SIG_DFL);
221
222 char **const newargv=new char*[argc+2];
223 int n;
224
e8d78143 225 if(::arg()["config-name"]!="") {
4957a608
BH
226 progname+="-"+::arg()["config-name"];
227 L<<Logger::Error<<"Virtual configuration name: "<<::arg()["config-name"]<<endl;
12c86877
BH
228 }
229
230 newargv[0]=strdup(const_cast<char *>((progname+"-instance").c_str()));
231 for(n=1;n<argc;n++) {
4957a608 232 newargv[n]=argv[n];
12c86877
BH
233 }
234 newargv[n]=0;
235
236 L<<Logger::Error<<"Guardian is launching an instance"<<endl;
aced0e6c
BH
237 close(g_fd1[1]);
238 fclose(g_fp); // this closes g_fd2[0] for us
12c86877 239
aced0e6c 240 if(g_fd1[0]!= infd) {
4957a608
BH
241 dup2(g_fd1[0], infd);
242 close(g_fd1[0]);
12c86877
BH
243 }
244
aced0e6c 245 if(g_fd2[1]!= outfd) {
4957a608
BH
246 dup2(g_fd2[1], outfd);
247 close(g_fd2[1]);
12c86877 248 }
c1663439 249 if(execvp(argv[0], newargv)<0) {
4957a608
BH
250 L<<Logger::Error<<"Unable to execvp '"<<argv[0]<<"': "<<strerror(errno)<<endl;
251 char **p=newargv;
252 while(*p)
253 L<<Logger::Error<<*p++<<endl;
12c86877 254
4957a608 255 exit(1);
12c86877 256 }
c1663439 257 L<<Logger::Error<<"execvp returned!!"<<endl;
12c86877
BH
258 // never reached
259 }
260 else if(pid>0) { // parent
aced0e6c
BH
261 close(g_fd1[0]);
262 close(g_fd2[1]);
12c86877
BH
263
264 if(first) {
4957a608
BH
265 first=false;
266 signal(SIGTERM, takedown);
12c86877 267
4957a608
BH
268 signal(SIGHUP, SIG_IGN);
269 signal(SIGUSR1, SIG_IGN);
270 signal(SIGUSR2, SIG_IGN);
12c86877 271
4957a608 272 writePid();
12c86877 273 }
aced0e6c 274 pthread_mutex_unlock(&g_guardian_lock);
12c86877
BH
275 int status;
276 cpid=pid;
277 for(;;) {
4957a608
BH
278 int ret=waitpid(pid,&status,WNOHANG);
279
280 if(ret<0) {
281 L<<Logger::Error<<"In guardian loop, waitpid returned error: "<<strerror(errno)<<endl;
282 L<<Logger::Error<<"Dying"<<endl;
283 exit(1);
284 }
285 else if(ret) // something exited
286 break;
287 else { // child is alive
288 // execute some kind of ping here
289 if(DLQuitPlease())
290 takedown(1); // needs a parameter..
291 setStatus("Child running on pid "+itoa(pid));
292 sleep(1);
293 }
12c86877 294 }
aced0e6c
BH
295
296 pthread_mutex_lock(&g_guardian_lock);
297 close(g_fd1[1]);
298 fclose(g_fp);
299 g_fp=0;
12c86877
BH
300
301 if(WIFEXITED(status)) {
4957a608
BH
302 int ret=WEXITSTATUS(status);
303
304 if(ret==99) {
305 L<<Logger::Error<<"Child requested a stop, exiting"<<endl;
306 exit(1);
307 }
308 setStatus("Child died with code "+itoa(ret));
309 L<<Logger::Error<<"Our pdns instance exited with code "<<ret<<endl;
310 L<<Logger::Error<<"Respawning"<<endl;
311
312 sleep(1);
313 continue;
12c86877
BH
314 }
315 if(WIFSIGNALED(status)) {
4957a608
BH
316 int sig=WTERMSIG(status);
317 setStatus("Child died because of signal "+itoa(sig));
318 L<<Logger::Error<<"Our pdns instance ("<<pid<<") exited after signal "<<sig<<endl;
12c86877 319#ifdef WCOREDUMP
4957a608
BH
320 if(WCOREDUMP(status))
321 L<<Logger::Error<<"Dumped core"<<endl;
12c86877
BH
322#endif
323
4957a608
BH
324 L<<Logger::Error<<"Respawning"<<endl;
325 sleep(1);
326 continue;
12c86877
BH
327 }
328 L<<Logger::Error<<"No clue what happened! Respawning"<<endl;
329 }
330 else {
331 L<<Logger::Error<<"Unable to fork: "<<strerror(errno)<<endl;
332 exit(1);
333 }
334 }
335}
336
337static void UNIX_declareArguments()
338{
65efcdbc 339 ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR;
e8d78143
BH
340 ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
341 ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
342 ::arg().set("module-dir","Default directory for modules")=LIBDIR;
343 ::arg().set("chroot","If set, chroot to this directory for more security")="";
344 ::arg().set("logging-facility","Log under a specific facility")="";
345 ::arg().set("daemon","Operate as a daemon")="no";
12c86877
BH
346
347}
348
349static void loadModules()
350{
e8d78143 351 if(!::arg()["load-modules"].empty()) {
12c86877
BH
352 vector<string>modules;
353
e8d78143 354 stringtok(modules,::arg()["load-modules"],",");
12c86877
BH
355
356 for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i) {
357 bool res;
358 const string &module=*i;
359
360 if(module.find(".")==string::npos)
4957a608 361 res=UeberBackend::loadmodule(::arg()["module-dir"]+"/lib"+module+"backend.so");
12c86877 362 else if(module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.')) // absolute or current path
4957a608 363 res=UeberBackend::loadmodule(module);
12c86877 364 else
4957a608 365 res=UeberBackend::loadmodule(::arg()["module-dir"]+"/"+module);
12c86877
BH
366
367 if(res==false) {
4957a608
BH
368 L<<Logger::Error<<"receiver unable to load module "<<module<<endl;
369 exit(1);
12c86877
BH
370 }
371 }
372 }
373}
374
30ea693c 375
12c86877
BH
376
377#ifdef __linux__
378#include <execinfo.h>
379static void tbhandler(int num)
380{
381 L<<Logger::Critical<<"Got a signal "<<num<<", attempting to print trace: "<<endl;
382 void *array[20]; //only care about last 17 functions (3 taken with tracing support)
383 size_t size;
384 char **strings;
385 size_t i;
386
387 size = backtrace (array, 20);
388 strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work
389
390 for (i = 0; i < size; i++) //skip useless functions
391 L<<Logger::Error<<strings[i]<<endl;
392
393
394 signal(SIGABRT, SIG_DFL);
395 abort();//hopefully will give core
396
397}
398#endif
399
400//! The main function of pdns, the pdns process
401int main(int argc, char **argv)
402{
02116dff
BH
403 reportAllTypes(); // init MOADNSParser
404
12c86877
BH
405 s_programname="pdns";
406 s_starttime=time(0);
407
408#ifdef __linux__
409 signal(SIGSEGV,tbhandler);
410 signal(SIGFPE,tbhandler);
411 signal(SIGABRT,tbhandler);
412 signal(SIGILL,tbhandler);
413#endif
414
35b9a6ff
PD
415#if __GNUC__ >= 3
416 std::ios_base::sync_with_stdio(false);
417#endif
12c86877
BH
418
419 L.toConsole(Logger::Warning);
420 try {
421 declareArguments();
422 UNIX_declareArguments();
c4db07b7 423
e8d78143 424 ::arg().laxParse(argc,argv); // do a lax parse
12c86877 425
c4db07b7 426 if(::arg().mustDo("version")) {
30ea693c
PD
427 cerr<<"Version: "VERSION", compiled on "<<__DATE__", "__TIME__;
428#ifdef __GNUC__
429 cerr<<" with gcc version "<<__VERSION__;
430#endif
431 cout<<endl;
c4db07b7
PD
432 exit(99);
433 }
434
e8d78143
BH
435 if(::arg()["config-name"]!="")
436 s_programname+="-"+::arg()["config-name"];
12c86877
BH
437
438 (void)theL(s_programname);
439
e8d78143 440 string configname=::arg()["config-dir"]+"/"+s_programname+".conf";
12c86877
BH
441 cleanSlashes(configname);
442
e8d78143
BH
443 if(!::arg().mustDo("config") && !::arg().mustDo("no-config")) // "config" == print a configuration file
444 ::arg().laxFile(configname.c_str());
12c86877 445
e8d78143
BH
446 ::arg().laxParse(argc,argv); // reparse so the commandline still wins
447 if(!::arg()["logging-facility"].empty()) {
f8499e52
BH
448 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
449 if(val >= 0)
450 theL().setFacility(val);
6e2514e4 451 else
4957a608 452 L<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
12c86877
BH
453 }
454
e8d78143
BH
455 L.setLoglevel((Logger::Urgency)(::arg().asNum("loglevel")));
456 L.toConsole((Logger::Urgency)(::arg().asNum("loglevel")));
12c86877 457
e8d78143
BH
458 if(::arg().mustDo("help") || ::arg().mustDo("config")) {
459 ::arg().set("daemon")="no";
460 ::arg().set("guardian")="no";
12c86877
BH
461 }
462
e8d78143
BH
463 if(::arg().mustDo("guardian") && !isGuarded(argv)) {
464 if(::arg().mustDo("daemon")) {
4957a608
BH
465 L.toConsole(Logger::Critical);
466 daemonize();
12c86877
BH
467 }
468 guardian(argc, argv);
469 // never get here, guardian will reinvoke process
470 cerr<<"Um, we did get here!"<<endl;
471 }
45fdd612 472
12c86877
BH
473
474 // we really need to do work - either standalone or as an instance
5488e86b
PD
475
476#ifdef __linux__
477 if(!::arg().mustDo("traceback-handler")) {
478 L<<Logger::Warning<<"Disabling traceback handler"<<endl;
479 signal(SIGSEGV,SIG_DFL);
480 signal(SIGFPE,SIG_DFL);
481 signal(SIGABRT,SIG_DFL);
482 signal(SIGILL,SIG_DFL);
483 }
484#endif
485
a28a204a
BH
486 seedRandom(::arg()["entropy-source"]);
487
12c86877 488 loadModules();
e8d78143 489 BackendMakers().launch(::arg()["launch"]); // vrooooom!
f4137d84 490
e8d78143 491 if(!::arg().getCommands().empty()) {
49daa3cd
BH
492 cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl;
493 exit(99);
494 }
f4137d84 495
e8d78143 496 if(::arg().mustDo("help")) {
12c86877 497 cerr<<"syntax:"<<endl<<endl;
e8d78143 498 cerr<<::arg().helpstring(::arg()["help"])<<endl;
12c86877
BH
499 exit(99);
500 }
501
e8d78143
BH
502 if(::arg().mustDo("config")) {
503 cout<<::arg().configstring()<<endl;
12c86877
BH
504 exit(99);
505 }
506
e8d78143 507 if(::arg().mustDo("list-modules")) {
12c86877
BH
508 vector<string>modules=BackendMakers().getModules();
509 cerr<<"Modules available:"<<endl;
510 for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i)
4957a608 511 cout<<*i<<endl;
12c86877
BH
512
513 exit(99);
514 }
da44c9ea 515
203c0755
BH
516 if(::arg().mustDo("fancy-records")) {
517 reportFancyTypes();
518 }
519
e8d78143 520 if(!::arg().asNum("local-port")) {
da44c9ea
BH
521 L<<Logger::Error<<"Unable to launch, binding to no port or port 0 makes no sense"<<endl;
522 exit(99); // this isn't going to fix itself either
523 }
12c86877
BH
524 if(!BackendMakers().numLauncheable()) {
525 L<<Logger::Error<<"Unable to launch, no backends configured for querying"<<endl;
da44c9ea 526 exit(99); // this isn't going to fix itself either
12c86877 527 }
e8d78143 528 if(::arg().mustDo("daemon")) {
12c86877
BH
529 L.toConsole(Logger::None);
530 if(!isGuarded(argv))
4957a608 531 daemonize();
12c86877
BH
532 }
533
7f7b8d55
BH
534 if(::arg()["server-id"].empty()) {
535 char tmp[128];
536 gethostname(tmp, sizeof(tmp)-1);
537 ::arg().set("server-id")=tmp;
538 }
539
12c86877
BH
540 if(isGuarded(argv)) {
541 L<<Logger::Warning<<"This is a guarded instance of pdns"<<endl;
542 dl=new DynListener; // listens on stdin
543 }
544 else {
545 L<<Logger::Warning<<"This is a standalone pdns"<<endl;
546
e8d78143 547 if(::arg().mustDo("control-console"))
4957a608 548 dl=new DynListener();
12c86877 549 else
4957a608 550 dl=new DynListener(s_programname);
12c86877
BH
551
552 writePid();
553 }
3c90953e
PD
554 DynListener::registerFunc("SHOW",&DLShowHandler, "show a specific statistic or * to get a list", "<statistic>");
555 DynListener::registerFunc("RPING",&DLPingHandler, "ping instance");
556 DynListener::registerFunc("QUIT",&DLRQuitHandler, "quit daemon");
557 DynListener::registerFunc("UPTIME",&DLUptimeHandler, "get instance uptime");
558 DynListener::registerFunc("NOTIFY-HOST",&DLNotifyHostHandler, "notify host for specific domain", "<domain> <host>");
559 DynListener::registerFunc("NOTIFY",&DLNotifyHandler, "queue a notification", "<domain>");
560 DynListener::registerFunc("RELOAD",&DLReloadHandler, "reload all zones");
561 DynListener::registerFunc("REDISCOVER",&DLRediscoverHandler, "discover any new zones");
562 DynListener::registerFunc("VERSION",&DLVersionHandler, "get instance version");
563 DynListener::registerFunc("PURGE",&DLPurgeHandler, "purge entries from packet cache", "[<record>]");
564 DynListener::registerFunc("CCOUNTS",&DLCCHandler, "get cache statistics");
565 DynListener::registerFunc("SET",&DLSettingsHandler, "set config variables", "<var> <value>");
566 DynListener::registerFunc("RETRIEVE",&DLNotifyRetrieveHandler, "retrieve slave domain", "<domain>");
64bcb6be 567 DynListener::registerFunc("CURRENT-CONFIG",&DLCurrentConfigHandler, "Retrieve the current configuration");
040712e0
BH
568
569 if(!::arg()["tcp-control-address"].empty()) {
570 DynListener* dlTCP=new DynListener(ComboAddress(::arg()["tcp-control-address"], ::arg().asNum("tcp-control-port")));
571 dlTCP->go();
572 }
12c86877 573
12c86877 574 // reparse, with error checking
e8d78143
BH
575 if(!::arg().mustDo("no-config"))
576 ::arg().file(configname.c_str());
577 ::arg().parse(argc,argv);
12c86877
BH
578 UeberBackend::go();
579 N=new UDPNameserver; // this fails when we are not root, throws exception
580
e8d78143 581 if(!::arg().mustDo("disable-tcp"))
12c86877
BH
582 TN=new TCPNameserver;
583 }
584 catch(const ArgException &A) {
585 L<<Logger::Error<<"Fatal error: "<<A.reason<<endl;
586 exit(1);
587 }
588
589 declareStats();
590 DLOG(L<<Logger::Warning<<"Verbose logging in effect"<<endl);
30ea693c
PD
591
592 L<<Logger::Warning<<"PowerDNS "<<VERSION<<" (C) 2001-2013 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
593#ifdef __GNUC__
594 L<<", gcc "__VERSION__;
595#endif // add other compilers here
596 L<<") starting up"<<endl;
597
598 L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. "
599 "This is free software, and you are welcome to redistribute it "
600 "according to the terms of the GPL version 2."<<endl;
12c86877
BH
601
602
603 try {
604
605 mainthread();
606 }
607 catch(AhuException &AE) {
e8d78143 608 if(!::arg().mustDo("daemon"))
12c86877
BH
609 cerr<<"Exiting because: "<<AE.reason<<endl;
610 L<<Logger::Error<<"Exiting because: "<<AE.reason<<endl;
611 }
adc10f99 612 catch(std::exception &e) {
e8d78143 613 if(!::arg().mustDo("daemon"))
12c86877
BH
614 cerr<<"Exiting because of STL error: "<<e.what()<<endl;
615 L<<Logger::Error<<"Exiting because of STL error: "<<e.what()<<endl;
616 }
617 catch(...) {
618 cerr<<"Uncaught exception of unknown type - sorry"<<endl;
619 }
620
621 exit(1);
622
623}
624
625