Example #1
0
File: main.c Project: sisoftrg/qico
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;
}
Example #2
0
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;
    }
}