int main(int argc,char **argv,char **envp) { int c,daemon=-1,rc,sesstype=SESSION_EMSI,line=0,call_flags=0; char *hostname=NULL,*str=NULL; FTNADDR_T(fa); #ifndef HAVE_SETPROCTITLE setargspace(argc,argv,envp); #endif #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); #endif while((c=getopt(argc, argv, "hI:da:ni:c:tbv"))!=EOF) { switch(c) { case 'c': daemon=12; str=optarg; while(str&&*str) { switch(toupper(*str)) { case 'N': call_flags=0; break; case 'I': call_flags|=1; break; case 'A': call_flags|=2; break; default: write_log("unknown call option: %c", *optarg); exit(S_FAILURE); } str++; } break; case 'i': hostname=optarg; break; case 'I': configname=optarg; break; case 'd': daemon=1; break; case 'a': daemon=0; sesstype=SESSION_AUTO; if(!strncasecmp(optarg,"**emsi",6)|| !strncasecmp(optarg,"auto",4))sesstype=SESSION_EMSI; #ifdef WITH_BINKP if(strncasecmp(optarg,"binkp",5)&& (*optarg!=0x80||!optarg[1]||optarg[2]))break; sesstype=SESSION_BINKP; case 'b': bink=1; #endif break; case 'n': daemon=2; break; case 't': daemon=3; break; case 'v': u_vers(progname); default: usage(argv[0]); } } if(!hostname&&daemon<0)usage(argv[0]); getsysinfo();ssock=lins_sock=uis_sock=-1; if(!readconfig(configname)) { write_log("there was some errors parsing '%s', aborting",configname); exit(S_FAILURE); } if(!log_init(cfgs(CFG_MASTERLOG),NULL)) { write_log("can't open master log '%s'",ccs); exit(S_FAILURE); } #ifdef NEED_DEBUG parse_log_levels(); if(facilities_levels['C']>=1)dumpconfig(); #endif psubsts=parsesubsts(cfgfasl(CFG_SUBST)); #ifdef NEED_DEBUG if(facilities_levels['C']>=1) { subst_t *s; dialine_t *l; for(s=psubsts;s;s=s->next) { write_log("subst for %s [%d]",ftnaddrtoa(&s->addr),s->nhids); for(l=s->hiddens;l;l=l->next) write_log(" * %s,%s,%s,%d,%d",l->phone,l->host,l->timegaps,l->flags,l->num); } } #endif log_done(); if(daemon==3)exit(S_OK); if(hostname||daemon==12) { if(!parseftnaddr(argv[optind],&fa,&DEFADDR,0)) { write_log("can't parse address '%s'",argv[optind]); exit(S_FAILURE); } optind++; } if(hostname) { is_ip=1; rnode=xcalloc(1,sizeof(ninfo_t)); xstrcpy(ip_id,"ipline",10); rnode->tty=bink?"binkp":"tcpip"; if(!log_init(cfgs(CFG_LOG),rnode->tty)) { write_log("can't open log %s",ccs); exit(S_FAILURE); } signal(SIGINT,sigerr); signal(SIGTERM,sigerr); signal(SIGSEGV,sigerr); signal(SIGPIPE,SIG_IGN); IFPerl(perl_init(cfgs(CFG_PERLFILE),0)); log_callback=NULL;xsend_cb=NULL; ssock=cls_conn(CLS_LINE,cfgs(CFG_SERVER),NULL); if(ssock<0)write_log("can't connect to server: %s",strerror(errno)); else log_callback=vlogs; rc=aso_init(cfgs(CFG_ASOOUTBOUND),cfgs(CFG_BSOOUTBOUND),cfgs(CFG_QSTOUTBOUND),cfgal(CFG_ADDRESS)->addr.z); if(!rc) { write_log("No outbound defined"); stopit(S_FAILURE); } rc=do_call(&fa,hostname,NULL); aso_done(); stopit(rc); } if(daemon==12) { if(optind<argc) { if(1!=sscanf(argv[optind],"%d",&line)) { write_log("can't parse line number '%s'!\n",argv[optind]); exit(S_FAILURE); } } else line = 0; log_callback=NULL;xsend_cb=NULL; ssock=cls_conn(CLS_LINE,cfgs(CFG_SERVER),NULL); if(ssock<0)write_log("can't connect to server: %s",strerror(errno)); else log_callback=vlogs; rc=aso_init(cfgs(CFG_ASOOUTBOUND),cfgs(CFG_BSOOUTBOUND),cfgs(CFG_QSTOUTBOUND),cfgal(CFG_ADDRESS)->addr.z); if(!rc) { write_log("No outbound defined"); cls_close(ssock); exit(S_FAILURE); } if(aso_locknode(&fa,LCK_c)) { signal(SIGINT,sigerr); signal(SIGTERM,sigerr); signal(SIGSEGV,sigerr); signal(SIGPIPE,SIG_IGN); IFPerl(perl_init(cfgs(CFG_PERLFILE),0)); rc=force_call(&fa,line,call_flags); aso_unlocknode(&fa,LCK_x); } else rc=S_FAILURE; if(rc&S_MASK)write_log("can't call to %s",ftnaddrtoa(&fa)); aso_done(); stopit(rc); } switch(daemon) { case 1: daemon_mode(); break; case 0: answer_mode(sesstype); break; case 2: compile_nodelists(); break; } return S_OK; }
void logger::init(const config_tree& a_cfg, const sigset_t* a_ignore_signals, bool a_install_finalizer) { if (m_initialized) throw std::runtime_error("Logger already initialized!"); std::lock_guard<std::mutex> guard(m_mutex); do_finalize(); try { m_show_location = a_cfg.get<bool> ("logger.show-location", m_show_location); m_show_fun_namespaces = a_cfg.get<int> ("logger.show-fun-namespaces", m_show_fun_namespaces); m_show_category = a_cfg.get<bool> ("logger.show-category", m_show_category); m_show_ident = a_cfg.get<bool> ("logger.show-ident", m_show_ident); m_show_thread = a_cfg.get<bool> ("logger.show-thread", m_show_thread); m_fatal_kill_signal = a_cfg.get<int> ("logger.fatal-kill-signal",m_fatal_kill_signal); m_ident = a_cfg.get<std::string>("logger.ident", m_ident); m_ident = replace_macros(m_ident); std::string ts = a_cfg.get<std::string>("logger.timestamp", "time-usec"); m_timestamp_type = parse_stamp_type(ts); std::string levs = a_cfg.get<std::string>("logger.levels", ""); if (!levs.empty()) set_level_filter(static_cast<log_level>(parse_log_levels(levs))); std::string ls = a_cfg.get<std::string>("logger.min-level-filter", "info"); if (!levs.empty() && !ls.empty()) std::runtime_error ("Either 'levels' or 'min-level-filter' option is permitted!"); set_min_level_filter(parse_log_level(ls)); long timeout_ms = a_cfg.get<int> ("logger.wait-timeout-ms", 1000); m_wait_timeout = timespec{timeout_ms / 1000, timeout_ms % 1000 * 1000000L}; m_sched_yield_us = a_cfg.get<long> ("logger.sched-yield-us", -1); m_silent_finish = a_cfg.get<bool> ("logger.silent-finish", false); m_block_signals = a_cfg.get<bool> ("logger.block-signals", true); if ((int)m_timestamp_type < 0) throw std::runtime_error("Invalid timestamp type: " + ts); // Install crash signal handlers // (SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM) if (a_cfg.get("logger.handle-crash-signals", true)) { sigset_t sset = sig_members_parse (a_cfg.get("logger.handle-crash-signals.signals",""), UTXX_SRC); // Remove signals from the sset that are handled externally if (a_ignore_signals) for (uint i=1; i < sig_names_count(); ++i) if (sigismember(a_ignore_signals, i)) sigdelset(&sset, i); if (install_sighandler(true, &sset)) { auto old = m_crash_sigset.exchange(new sigset_t(sset)); if (!old) delete old; } } //logger_impl::msg_info info(NULL, 0); //query_timestamp(info); logger_impl_mgr& lim = logger_impl_mgr::instance(); std::lock_guard<std::mutex> guard(lim.mutex()); // Check the list of registered implementations. If corresponding // configuration section is found, initialize the implementation. for(logger_impl_mgr::impl_map_t::iterator it=lim.implementations().begin(); it != lim.implementations().end(); ++it) { std::string path = std::string("logger.") + it->first; if (a_cfg.get_child_optional(path)) { // Determine if implementation of this type is already // registered with the logger bool found = false; for(implementations_vector::iterator im = m_implementations.begin(), iend = m_implementations.end(); im != iend; ++im) if (it->first == (*im)->name()) { found = true; break; } if (found) throw badarg_error("Implementation '", it->first, "' is already registered with the logger!"); // A call to it->second() creates a logger_impl* pointer. // We need to call implementation's init function that may throw, // so use RAII to guarantee proper cleanup. logger_impl_mgr::impl_callback_t& f = it->second; m_implementations.emplace_back( f(it->first.c_str()) ); auto& i = m_implementations.back(); i->set_log_mgr(this); i->init(a_cfg); } } m_initialized = true; m_abort = false; m_thread.reset(new std::thread([this]() { this->run(); })); if (!m_finalizer_installed && a_install_finalizer) { atexit(&finalize_logger_at_exit); m_finalizer_installed = true; } } catch (std::runtime_error& e) { if (m_error) m_error(e.what()); else throw; } }