]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/receiver.cc
we had per-program CPPFLAGS for pdnssec and pdns_server for no good reason (they...
[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
BH
137
138static string DLRestHandler(const vector<string>&parts, pid_t ppid)
139{
140 string line;
141
142 for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i) {
143 if(i!=parts.begin())
144 line.append(1,' ');
145 line.append(*i);
146 }
147 line.append(1,'\n');
148
aced0e6c
BH
149 Lock l(&g_guardian_lock);
150
151 try {
152 writen2(g_fd1[1],line.c_str(),line.size()+1);
153 }
154 catch(AhuException &ae) {
155 return "Error communicating with instance: "+ae.reason;
156 }
12c86877 157 char mesg[512];
20ca8e7d 158 string response;
aced0e6c 159 while(fgets(mesg,sizeof(mesg),g_fp)) {
20ca8e7d
BH
160 if(*mesg=='\n')
161 break;
162 response+=mesg;
163 }
040712e0 164 boost::trim_right(response);
20ca8e7d 165 return response;
12c86877
BH
166}
167
168static string DLCycleHandler(const vector<string>&parts, pid_t ppid)
169{
aced0e6c
BH
170 kill(cpid, SIGKILL); // why?
171 kill(cpid, SIGKILL); // why?
88def049 172 sleep(1);
12c86877
BH
173 return "ok";
174}
175
176static int guardian(int argc, char **argv)
177{
178 if(isGuarded(argv))
179 return 0;
180
181 int infd=0, outfd=1;
182
183 DynListener dlg(s_programname);
3c90953e
PD
184 dlg.registerFunc("QUIT",&DLQuitHandler, "quit daemon");
185 dlg.registerFunc("CYCLE",&DLCycleHandler, "restart instance");
186 dlg.registerFunc("PING",&DLPingHandler, "ping guardian");
187 dlg.registerFunc("STATUS",&DLStatusHandler, "get instance status from guardian");
12c86877
BH
188 dlg.registerRestFunc(&DLRestHandler);
189 dlg.go();
190 string progname=argv[0];
191
192 bool first=true;
193 cpid=0;
194
aced0e6c
BH
195 pthread_mutex_lock(&g_guardian_lock);
196
12c86877
BH
197 for(;;) {
198 int pid;
199 setStatus("Launching child");
aced0e6c
BH
200
201 if(pipe(g_fd1)<0 || pipe(g_fd2)<0) {
12c86877
BH
202 L<<Logger::Critical<<"Unable to open pipe for coprocess: "<<strerror(errno)<<endl;
203 exit(1);
204 }
205
aced0e6c
BH
206 if(!(g_fp=fdopen(g_fd2[0],"r"))) {
207 L<<Logger::Critical<<"Unable to associate a file pointer with pipe: "<<stringerror()<<endl;
208 exit(1);
209 }
210 setbuf(g_fp,0); // no buffering please, confuses select
211
12c86877
BH
212 if(!(pid=fork())) { // child
213 signal(SIGTERM, SIG_DFL);
214
215 signal(SIGHUP, SIG_DFL);
216 signal(SIGUSR1, SIG_DFL);
217 signal(SIGUSR2, SIG_DFL);
218
219 char **const newargv=new char*[argc+2];
220 int n;
221
e8d78143 222 if(::arg()["config-name"]!="") {
4957a608
BH
223 progname+="-"+::arg()["config-name"];
224 L<<Logger::Error<<"Virtual configuration name: "<<::arg()["config-name"]<<endl;
12c86877
BH
225 }
226
227 newargv[0]=strdup(const_cast<char *>((progname+"-instance").c_str()));
228 for(n=1;n<argc;n++) {
4957a608 229 newargv[n]=argv[n];
12c86877
BH
230 }
231 newargv[n]=0;
232
233 L<<Logger::Error<<"Guardian is launching an instance"<<endl;
aced0e6c
BH
234 close(g_fd1[1]);
235 fclose(g_fp); // this closes g_fd2[0] for us
12c86877 236
aced0e6c 237 if(g_fd1[0]!= infd) {
4957a608
BH
238 dup2(g_fd1[0], infd);
239 close(g_fd1[0]);
12c86877
BH
240 }
241
aced0e6c 242 if(g_fd2[1]!= outfd) {
4957a608
BH
243 dup2(g_fd2[1], outfd);
244 close(g_fd2[1]);
12c86877 245 }
c1663439 246 if(execvp(argv[0], newargv)<0) {
4957a608
BH
247 L<<Logger::Error<<"Unable to execvp '"<<argv[0]<<"': "<<strerror(errno)<<endl;
248 char **p=newargv;
249 while(*p)
250 L<<Logger::Error<<*p++<<endl;
12c86877 251
4957a608 252 exit(1);
12c86877 253 }
c1663439 254 L<<Logger::Error<<"execvp returned!!"<<endl;
12c86877
BH
255 // never reached
256 }
257 else if(pid>0) { // parent
aced0e6c
BH
258 close(g_fd1[0]);
259 close(g_fd2[1]);
12c86877
BH
260
261 if(first) {
4957a608
BH
262 first=false;
263 signal(SIGTERM, takedown);
12c86877 264
4957a608
BH
265 signal(SIGHUP, SIG_IGN);
266 signal(SIGUSR1, SIG_IGN);
267 signal(SIGUSR2, SIG_IGN);
12c86877 268
4957a608 269 writePid();
12c86877 270 }
aced0e6c 271 pthread_mutex_unlock(&g_guardian_lock);
12c86877
BH
272 int status;
273 cpid=pid;
274 for(;;) {
4957a608
BH
275 int ret=waitpid(pid,&status,WNOHANG);
276
277 if(ret<0) {
278 L<<Logger::Error<<"In guardian loop, waitpid returned error: "<<strerror(errno)<<endl;
279 L<<Logger::Error<<"Dying"<<endl;
280 exit(1);
281 }
282 else if(ret) // something exited
283 break;
284 else { // child is alive
285 // execute some kind of ping here
286 if(DLQuitPlease())
287 takedown(1); // needs a parameter..
288 setStatus("Child running on pid "+itoa(pid));
289 sleep(1);
290 }
12c86877 291 }
aced0e6c
BH
292
293 pthread_mutex_lock(&g_guardian_lock);
294 close(g_fd1[1]);
295 fclose(g_fp);
296 g_fp=0;
12c86877
BH
297
298 if(WIFEXITED(status)) {
4957a608
BH
299 int ret=WEXITSTATUS(status);
300
301 if(ret==99) {
302 L<<Logger::Error<<"Child requested a stop, exiting"<<endl;
303 exit(1);
304 }
305 setStatus("Child died with code "+itoa(ret));
306 L<<Logger::Error<<"Our pdns instance exited with code "<<ret<<endl;
307 L<<Logger::Error<<"Respawning"<<endl;
308
309 sleep(1);
310 continue;
12c86877
BH
311 }
312 if(WIFSIGNALED(status)) {
4957a608
BH
313 int sig=WTERMSIG(status);
314 setStatus("Child died because of signal "+itoa(sig));
315 L<<Logger::Error<<"Our pdns instance ("<<pid<<") exited after signal "<<sig<<endl;
12c86877 316#ifdef WCOREDUMP
4957a608
BH
317 if(WCOREDUMP(status))
318 L<<Logger::Error<<"Dumped core"<<endl;
12c86877
BH
319#endif
320
4957a608
BH
321 L<<Logger::Error<<"Respawning"<<endl;
322 sleep(1);
323 continue;
12c86877
BH
324 }
325 L<<Logger::Error<<"No clue what happened! Respawning"<<endl;
326 }
327 else {
328 L<<Logger::Error<<"Unable to fork: "<<strerror(errno)<<endl;
329 exit(1);
330 }
331 }
332}
333
334static void UNIX_declareArguments()
335{
65efcdbc 336 ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR;
e8d78143
BH
337 ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
338 ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
339 ::arg().set("module-dir","Default directory for modules")=LIBDIR;
340 ::arg().set("chroot","If set, chroot to this directory for more security")="";
341 ::arg().set("logging-facility","Log under a specific facility")="";
342 ::arg().set("daemon","Operate as a daemon")="no";
12c86877
BH
343
344}
345
346static void loadModules()
347{
e8d78143 348 if(!::arg()["load-modules"].empty()) {
12c86877
BH
349 vector<string>modules;
350
e8d78143 351 stringtok(modules,::arg()["load-modules"],",");
12c86877
BH
352
353 for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i) {
354 bool res;
355 const string &module=*i;
356
357 if(module.find(".")==string::npos)
4957a608 358 res=UeberBackend::loadmodule(::arg()["module-dir"]+"/lib"+module+"backend.so");
12c86877 359 else if(module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.')) // absolute or current path
4957a608 360 res=UeberBackend::loadmodule(module);
12c86877 361 else
4957a608 362 res=UeberBackend::loadmodule(::arg()["module-dir"]+"/"+module);
12c86877
BH
363
364 if(res==false) {
4957a608
BH
365 L<<Logger::Error<<"receiver unable to load module "<<module<<endl;
366 exit(1);
12c86877
BH
367 }
368 }
369 }
370}
371
372
373
374#ifdef __linux__
375#include <execinfo.h>
376static void tbhandler(int num)
377{
378 L<<Logger::Critical<<"Got a signal "<<num<<", attempting to print trace: "<<endl;
379 void *array[20]; //only care about last 17 functions (3 taken with tracing support)
380 size_t size;
381 char **strings;
382 size_t i;
383
384 size = backtrace (array, 20);
385 strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work
386
387 for (i = 0; i < size; i++) //skip useless functions
388 L<<Logger::Error<<strings[i]<<endl;
389
390
391 signal(SIGABRT, SIG_DFL);
392 abort();//hopefully will give core
393
394}
395#endif
396
397//! The main function of pdns, the pdns process
398int main(int argc, char **argv)
399{
02116dff
BH
400 reportAllTypes(); // init MOADNSParser
401
12c86877
BH
402 s_programname="pdns";
403 s_starttime=time(0);
404
405#ifdef __linux__
406 signal(SIGSEGV,tbhandler);
407 signal(SIGFPE,tbhandler);
408 signal(SIGABRT,tbhandler);
409 signal(SIGILL,tbhandler);
410#endif
411
412
413 L.toConsole(Logger::Warning);
414 try {
415 declareArguments();
416 UNIX_declareArguments();
c4db07b7 417
e8d78143 418 ::arg().laxParse(argc,argv); // do a lax parse
12c86877 419
c4db07b7
PD
420 if(::arg().mustDo("version")) {
421 cerr<<"Version: "VERSION", compiled on "<<__DATE__", "__TIME__;
422#ifdef __GNUC__
423 cerr<<" with gcc version "<<__VERSION__;
424#endif
425 cout<<endl;
426 exit(99);
427 }
428
e8d78143
BH
429 if(::arg()["config-name"]!="")
430 s_programname+="-"+::arg()["config-name"];
12c86877
BH
431
432 (void)theL(s_programname);
433
e8d78143 434 string configname=::arg()["config-dir"]+"/"+s_programname+".conf";
12c86877
BH
435 cleanSlashes(configname);
436
e8d78143
BH
437 if(!::arg().mustDo("config") && !::arg().mustDo("no-config")) // "config" == print a configuration file
438 ::arg().laxFile(configname.c_str());
12c86877 439
e8d78143
BH
440 ::arg().laxParse(argc,argv); // reparse so the commandline still wins
441 if(!::arg()["logging-facility"].empty()) {
f8499e52
BH
442 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
443 if(val >= 0)
444 theL().setFacility(val);
6e2514e4 445 else
4957a608 446 L<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
12c86877
BH
447 }
448
e8d78143
BH
449 L.setLoglevel((Logger::Urgency)(::arg().asNum("loglevel")));
450 L.toConsole((Logger::Urgency)(::arg().asNum("loglevel")));
12c86877 451
e8d78143
BH
452 if(::arg().mustDo("help") || ::arg().mustDo("config")) {
453 ::arg().set("daemon")="no";
454 ::arg().set("guardian")="no";
12c86877
BH
455 }
456
e8d78143
BH
457 if(::arg().mustDo("guardian") && !isGuarded(argv)) {
458 if(::arg().mustDo("daemon")) {
4957a608
BH
459 L.toConsole(Logger::Critical);
460 daemonize();
12c86877
BH
461 }
462 guardian(argc, argv);
463 // never get here, guardian will reinvoke process
464 cerr<<"Um, we did get here!"<<endl;
465 }
45fdd612 466
12c86877
BH
467
468 // we really need to do work - either standalone or as an instance
5488e86b
PD
469
470#ifdef __linux__
471 if(!::arg().mustDo("traceback-handler")) {
472 L<<Logger::Warning<<"Disabling traceback handler"<<endl;
473 signal(SIGSEGV,SIG_DFL);
474 signal(SIGFPE,SIG_DFL);
475 signal(SIGABRT,SIG_DFL);
476 signal(SIGILL,SIG_DFL);
477 }
478#endif
479
a28a204a
BH
480 seedRandom(::arg()["entropy-source"]);
481
12c86877 482 loadModules();
e8d78143 483 BackendMakers().launch(::arg()["launch"]); // vrooooom!
f4137d84 484
e8d78143 485 if(!::arg().getCommands().empty()) {
49daa3cd
BH
486 cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl;
487 exit(99);
488 }
f4137d84 489
e8d78143 490 if(::arg().mustDo("help")) {
12c86877 491 cerr<<"syntax:"<<endl<<endl;
e8d78143 492 cerr<<::arg().helpstring(::arg()["help"])<<endl;
12c86877
BH
493 exit(99);
494 }
495
e8d78143
BH
496 if(::arg().mustDo("config")) {
497 cout<<::arg().configstring()<<endl;
12c86877
BH
498 exit(99);
499 }
500
e8d78143 501 if(::arg().mustDo("list-modules")) {
12c86877
BH
502 vector<string>modules=BackendMakers().getModules();
503 cerr<<"Modules available:"<<endl;
504 for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i)
4957a608 505 cout<<*i<<endl;
12c86877
BH
506
507 exit(99);
508 }
da44c9ea 509
203c0755
BH
510 if(::arg().mustDo("fancy-records")) {
511 reportFancyTypes();
512 }
513
e8d78143 514 if(!::arg().asNum("local-port")) {
da44c9ea
BH
515 L<<Logger::Error<<"Unable to launch, binding to no port or port 0 makes no sense"<<endl;
516 exit(99); // this isn't going to fix itself either
517 }
12c86877
BH
518 if(!BackendMakers().numLauncheable()) {
519 L<<Logger::Error<<"Unable to launch, no backends configured for querying"<<endl;
da44c9ea 520 exit(99); // this isn't going to fix itself either
12c86877 521 }
e8d78143 522 if(::arg().mustDo("daemon")) {
12c86877
BH
523 L.toConsole(Logger::None);
524 if(!isGuarded(argv))
4957a608 525 daemonize();
12c86877
BH
526 }
527
7f7b8d55
BH
528 if(::arg()["server-id"].empty()) {
529 char tmp[128];
530 gethostname(tmp, sizeof(tmp)-1);
531 ::arg().set("server-id")=tmp;
532 }
533
12c86877
BH
534 if(isGuarded(argv)) {
535 L<<Logger::Warning<<"This is a guarded instance of pdns"<<endl;
536 dl=new DynListener; // listens on stdin
537 }
538 else {
539 L<<Logger::Warning<<"This is a standalone pdns"<<endl;
540
e8d78143 541 if(::arg().mustDo("control-console"))
4957a608 542 dl=new DynListener();
12c86877 543 else
4957a608 544 dl=new DynListener(s_programname);
12c86877
BH
545
546 writePid();
547 }
3c90953e
PD
548 DynListener::registerFunc("SHOW",&DLShowHandler, "show a specific statistic or * to get a list", "<statistic>");
549 DynListener::registerFunc("RPING",&DLPingHandler, "ping instance");
550 DynListener::registerFunc("QUIT",&DLRQuitHandler, "quit daemon");
551 DynListener::registerFunc("UPTIME",&DLUptimeHandler, "get instance uptime");
552 DynListener::registerFunc("NOTIFY-HOST",&DLNotifyHostHandler, "notify host for specific domain", "<domain> <host>");
553 DynListener::registerFunc("NOTIFY",&DLNotifyHandler, "queue a notification", "<domain>");
554 DynListener::registerFunc("RELOAD",&DLReloadHandler, "reload all zones");
555 DynListener::registerFunc("REDISCOVER",&DLRediscoverHandler, "discover any new zones");
556 DynListener::registerFunc("VERSION",&DLVersionHandler, "get instance version");
557 DynListener::registerFunc("PURGE",&DLPurgeHandler, "purge entries from packet cache", "[<record>]");
558 DynListener::registerFunc("CCOUNTS",&DLCCHandler, "get cache statistics");
559 DynListener::registerFunc("SET",&DLSettingsHandler, "set config variables", "<var> <value>");
560 DynListener::registerFunc("RETRIEVE",&DLNotifyRetrieveHandler, "retrieve slave domain", "<domain>");
040712e0
BH
561
562 if(!::arg()["tcp-control-address"].empty()) {
563 DynListener* dlTCP=new DynListener(ComboAddress(::arg()["tcp-control-address"], ::arg().asNum("tcp-control-port")));
564 dlTCP->go();
565 }
12c86877 566
12c86877 567 // reparse, with error checking
e8d78143
BH
568 if(!::arg().mustDo("no-config"))
569 ::arg().file(configname.c_str());
570 ::arg().parse(argc,argv);
12c86877
BH
571 UeberBackend::go();
572 N=new UDPNameserver; // this fails when we are not root, throws exception
573
e8d78143 574 if(!::arg().mustDo("disable-tcp"))
12c86877
BH
575 TN=new TCPNameserver;
576 }
577 catch(const ArgException &A) {
578 L<<Logger::Error<<"Fatal error: "<<A.reason<<endl;
579 exit(1);
580 }
581
582 declareStats();
583 DLOG(L<<Logger::Warning<<"Verbose logging in effect"<<endl);
584
7e66fc05 585 L<<Logger::Warning<<"PowerDNS "<<VERSION<<" (C) 2001-2012 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
45fdd612
BH
586#ifdef __GNUC__
587 L<<", gcc "__VERSION__;
588#endif // add other compilers here
589 L<<") starting up"<<endl;
12c86877
BH
590
591 L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. "
592 "This is free software, and you are welcome to redistribute it "
593 "according to the terms of the GPL version 2."<<endl;
594
595
596 try {
597
598 mainthread();
599 }
600 catch(AhuException &AE) {
e8d78143 601 if(!::arg().mustDo("daemon"))
12c86877
BH
602 cerr<<"Exiting because: "<<AE.reason<<endl;
603 L<<Logger::Error<<"Exiting because: "<<AE.reason<<endl;
604 }
adc10f99 605 catch(std::exception &e) {
e8d78143 606 if(!::arg().mustDo("daemon"))
12c86877
BH
607 cerr<<"Exiting because of STL error: "<<e.what()<<endl;
608 L<<Logger::Error<<"Exiting because of STL error: "<<e.what()<<endl;
609 }
610 catch(...) {
611 cerr<<"Uncaught exception of unknown type - sorry"<<endl;
612 }
613
614 exit(1);
615
616}
617
618