#include <stdio.h> #include <stdlib.h> #include <cumacros.h> #include <cumbia.h> #include <cueventloop.h> #include <signal.h> #include <cuserviceprovider.h> #include <cuthreadfactoryimpl.h> #include <cuthreadseventbridge.h> #include <pwd.h> #include <unistd.h> #include <calog.h> #include "config.h" #include "ca-tango-db-cache-mgr.h" #include <ca-receiver-a.h> #include <ca-opt-parser.h> CuEventLoopService *loo_s = nullptr; void on_int(int signo) { if(signo == SIGINT || signo == SIGTERM) { if(loo_s) loo_s->exit(); } } int drop_privileges(const char* user, char* msg) { struct passwd *p = getpwnam(user); if(p == nullptr) { snprintf(msg, 512, "failed to find UID for user \"%s\": %s", user, strerror(errno)); return 1; } if(setgid(p->pw_gid) != 0) { snprintf(msg, 512, "unable to drop group privileges to GID %d: %s", p->pw_gid, strerror(errno)); return 1; } if(setuid(p->pw_uid) != 0) { snprintf(msg, 512, "unable to drop user privileges to UID %d: %s", p->pw_uid, strerror(errno)); return 1; } if (setuid(0) != -1) { snprintf(msg, 512, "setuid back to zero succeeded, quitting as this is a security risk"); return 1; } msg[0] = '\0'; return 0; } int main(int argc, char *argv[]) { CaOptParser options; CuData opts = options.get_options(argc, argv, "ca-tango-db-cache-mgr"); if(options.errors.size() > 0) { perr("main.cpp: error in command line args: \n"); for(const std::string& e : options.errors) perr("- %s\n", e.c_str()); return EXIT_FAILURE; } // logging - 1. level CaLogFactory logfa; CuLogImplI *log_i = nullptr; CuLog::Level logle = static_cast<CuLog::Level>(opts["log_level"].toInt()); // logging - 2. where // drop privileges after this so that the log file can be created anywhere // CaFLog will change the file ownership to the unprivileged user after creation if(opts.has("log_where", "syslog")) log_i = logfa.create(CaLogFactory::Syslog, logle); else if(opts["log_where"].toString() != "console") log_i = logfa.create(CaLogFactory::LogFile, logle, opts["log_where"].toString().c_str(), opts.containsKey("user") ? vtoc2(opts, "user") : nullptr); else log_i = logfa.create(CaLogFactory::LogConsole, logle); // end logging setup log_i->write("main.cpp", "enter: " + std::string(argv[0]) + " version " + std::string(CATANGODBCACHEMGR_VERSION), CuLog::LevelAll); if(getuid() == 0 && !opts.containsKey("user")) { log_i->write("main.cpp", "cannot run as root and \"-s username\" command line argument missing", CuLog::LevelError); return EXIT_FAILURE; } else if(getuid() == 0 && opts.containsKey("user")) { char msg[512]; if(drop_privileges(vtoc2(opts, "user"), msg) != 0) { log_i->write("main.cpp", msg, CuLog::LevelError); return EXIT_FAILURE; } } printf("main.cpp: options %s\n", datos(opts)); if(!opts.containsKey("redis-host") || !opts.containsKey("host") || !opts.containsKey("port")) { perr("main.cpp: one or more options \"redis-host=\", \"host\" or \"port\" missing in the configuration file \"%s\"", vtoc2(opts, "dbfile")); return EXIT_FAILURE; } else { signal(SIGINT, on_int); signal(SIGTERM, on_int); Cumbia *cumbia = new Cumbia(); // The event loop is a single object shared across all Cumbia instances loo_s = new CuEventLoopService(); // register the service with the shared option set to true cumbia->getServiceProvider()->registerSharedService(CuServices::EventLoop, loo_s); CuData camgrtok("type", "catgcachemgr"); camgrtok.merge(opts); CuThreadFactoryImpl* thf_impl = new CuThreadFactoryImpl; CuThreadsEventBridgeFactory *thread_eb_f = new CuThreadsEventBridgeFactory; CaTgDbCacheMgr *cachemgr = new CaTgDbCacheMgr(cumbia, loo_s, opts, log_i); CaReceiver_A *server_a = nullptr; printf("\e[1;32m # \e[0mmain.cpp: starting receiver on %s\n", datos(opts)); server_a = new CaReceiver_A(opts); cumbia->registerActivity(server_a, cachemgr, CuData("type", "catgcachemgr-receiver"), *thf_impl, *thread_eb_f); printf("\e[1;32m # \e[0mmain.cpp: \e[1;32mca-tango-db-cache-mgr version \e[2;32m%s\e[0m started\n", CATANGODBCACHEMGR_VERSION); loo_s->exec(false); server_a->stop(); cumbia->unregisterActivity(server_a); delete cumbia; printf("\e[1;32m # \e[0mmain.cpp: ca-tango-db-cache-mgr exiting\n"); log_i->write("ca-tango-db-cache-mgr", "exiting", CuLog::LevelAll); delete log_i; } }