Back to index

nordugrid-arc-nox  1.1.0~rc6
main_unix.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #ifdef WIN32
00006 #include <arc/win32.h>
00007 #endif
00008 
00009 #include <fstream>
00010 #include <unistd.h>
00011 #include <sys/types.h>
00012 #include <pwd.h>
00013 #include <grp.h>
00014 #include <signal.h>
00015 #include <glibmm/fileutils.h>
00016 #include <glibmm/miscutils.h>
00017 
00018 #include <arc/ArcConfig.h>
00019 #include <arc/IniConfig.h>
00020 #include <arc/ArcLocation.h>
00021 #include <arc/Logger.h>
00022 #include <arc/XMLNode.h>
00023 #include <arc/StringConv.h>
00024 #include <arc/message/MCCLoader.h>
00025 
00026 #include "daemon.h"
00027 #include "../options.h"
00028 
00029 Arc::Daemon *main_daemon = NULL;
00030 Arc::Config config;
00031 Arc::MCCLoader *loader = NULL;
00032 Arc::Logger& logger = Arc::Logger::rootLogger;
00033 int exit_code = 0;
00034 
00035 static void shutdown(int)
00036 {
00037     logger.msg(Arc::VERBOSE, "shutdown");
00038     if(loader) delete loader;
00039     if(main_daemon) delete main_daemon;
00040     logger.msg(Arc::DEBUG, "exit");
00041     _exit(exit_code);
00042 }
00043 
00044 static void merge_options_and_config(Arc::Config& cfg, Arc::ServerOptions& opt)
00045 {
00046     Arc::XMLNode srv = cfg["Server"];
00047     if (!(bool)srv) {
00048       logger.msg(Arc::ERROR, "No server config part of config file");
00049       return;
00050     }
00051 
00052     if (opt.pid_file != "") {
00053         if (!(bool)srv["PidFile"]) {
00054            srv.NewChild("PidFile")=opt.pid_file;
00055         } else {
00056             srv["PidFile"] = opt.pid_file;
00057         }
00058     }
00059 
00060     if (opt.foreground == true) {
00061         if (!(bool)srv["Foreground"]) {
00062             srv.NewChild("Foreground");
00063         }
00064     }
00065 
00066     if (opt.user != "") {
00067         if (!(bool)srv["User"]) {
00068             srv.NewChild("User") = opt.user;
00069         } else {
00070             srv["User"] = opt.user;
00071         }
00072     }
00073 
00074     if (opt.group != "") {
00075         if (!(bool)srv["Group"]) {
00076             srv.NewChild("Group") = opt.group;
00077         } else {
00078             srv["Group"] = opt.group;
00079         }
00080     }
00081 }
00082 
00083 static std::string init_logger(Arc::XMLNode log, bool foreground)
00084 {
00085     /* setup root logger */
00086     Arc::LogFile* sd = NULL;
00087     Arc::LogLevel level = Arc::WARNING;
00088     if((bool)log["Level"] && !string_to_level((std::string)log["Level"], level)) {
00089       logger.msg(Arc::WARNING, "Unknown log level %s", (std::string)log["Level"]);
00090     }
00091     Arc::Logger::rootLogger.setThreshold(level);
00092 
00093     std::string log_file = (log["File"] ? (std::string)log["File"] : "/var/log/arched.log");
00094     sd = new Arc::LogFile(log_file);
00095     if((!sd) || (!(*sd))) {
00096       logger.msg(Arc::ERROR, "Failed to open log file: %s", (std::string)log["File"]);
00097       _exit(1);
00098     }
00099     if(log["Backups"]) {
00100       int backups;
00101       if(Arc::stringto((std::string)log["Backups"], backups)) {
00102         sd->setBackups(backups);
00103       }
00104     }
00105     if(log["Maxsize"]) {
00106       int maxsize;
00107       if(Arc::stringto((std::string)log["Maxsize"], maxsize)) {
00108         sd->setMaxSize(maxsize);
00109       }
00110     }
00111     Arc::Logger::rootLogger.removeDestinations();
00112     Arc::Logger::rootLogger.addDestination(*sd);
00113     if (foreground) {
00114       logger.msg(Arc::INFO, "Start foreground");
00115       Arc::LogStream *err = new Arc::LogStream(std::cerr);
00116       Arc::Logger::rootLogger.addDestination(*err);
00117     }
00118     return log_file;
00119 }
00120 
00121 static uid_t get_uid(const std::string &name)
00122 {
00123     struct passwd *ent;
00124     if (name[0] == '#') {
00125         return (atoi(&(name.c_str()[1])));
00126     }
00127     if (!(ent = getpwnam(name.c_str()))) {
00128         std::cerr << "Bad user name" << std::endl;
00129         exit(1);
00130     }
00131     return (ent->pw_uid);
00132 }
00133 
00134 static gid_t get_gid(const std::string &name)
00135 {
00136     struct group *ent;
00137     if (name[0] == '#') {
00138         return (atoi(&(name.c_str()[1])));
00139     }
00140     if (!(ent = getgrnam(name.c_str()))) {
00141         std::cerr << "Bad user name" << std::endl;
00142         exit(1);
00143     }
00144     return (ent->gr_gid);
00145 }
00146 
00147 static void init_config(const Arc::ServerOptions &options)
00148 {
00149     if (!options.xml_config_file.empty()) {
00150         if (Glib::file_test(options.xml_config_file,
00151             Glib::FILE_TEST_EXISTS) == false) {
00152             logger.msg(Arc::ERROR, "XML config file %s does not exist", options.xml_config_file);
00153             exit(1);
00154         }
00155         config.parse(options.xml_config_file.c_str());
00156         if (!config) {
00157             logger.msg(Arc::ERROR, "Failed to load service configuration from file %s", options.xml_config_file);
00158             exit(1);
00159         }
00160     } else if (!options.ini_config_file.empty()) {
00161         if (Glib::file_test(options.ini_config_file,
00162             Glib::FILE_TEST_EXISTS) == false) {
00163             logger.msg(Arc::ERROR, "INI config file %s does not exist", options.xml_config_file);
00164             exit(1);
00165         }
00166         Arc::IniConfig ini_parser(options.ini_config_file);
00167         if (ini_parser.Evaluate(config) == false) {
00168             logger.msg(Arc::ERROR, "Error evaluating profile");
00169             exit(1);
00170         }
00171         if (!config) {
00172             logger.msg(Arc::ERROR, "Failed to load service configuration from file %s", options.ini_config_file);
00173             exit(1);
00174         }
00175     } else {
00176         std::string ini_config_file = "/etc/arc/service.ini";
00177         if (Glib::file_test(ini_config_file,
00178             Glib::FILE_TEST_EXISTS) == false) {
00179                 std::string xml_config_file = "/etc/arc/service.xml";
00180                 if (Glib::file_test(xml_config_file,
00181                     Glib::FILE_TEST_EXISTS) == false) {
00182                 }
00183                 config.parse(xml_config_file.c_str());
00184         } else {
00185             Arc::IniConfig ini_parser(ini_config_file);
00186             ini_parser.Evaluate(config);
00187             if (ini_parser.Evaluate(config) == false) {
00188                 logger.msg(Arc::ERROR, "Error evaulating profile");
00189                 exit(1);
00190             }
00191         }
00192         if (!config) {
00193             logger.msg(Arc::ERROR, "Failed to load service configuration from any default config file");
00194             exit(1);
00195         }
00196     }
00197 }
00198 
00199 int main(int argc, char **argv)
00200 {
00201     // Ignore some signals
00202     signal(SIGTTOU,SIG_IGN);
00203     signal(SIGPIPE,SIG_IGN);
00204     // Temporary stderr destination for error messages
00205     Arc::LogStream logcerr(std::cerr);
00206     Arc::Logger::getRootLogger().addDestination(logcerr);
00207     /* Create options parser */
00208     Arc::ServerOptions options;
00209 
00210     if((argc>0) && (argv[0])) Arc::ArcLocation::Init(argv[0]);
00211 
00212     try {
00213         std::list<std::string> params = options.Parse(argc, argv);
00214         if (params.size() == 0) {
00215             /* Load and parse config file */
00216             init_config(options);
00217 
00218             // schema validation
00219             if (!options.schema_file.empty()) {
00220                 std::string err_msg;
00221                 bool ret = config.Validate(options.schema_file, err_msg);
00222                 if (ret == false) {
00223                     logger.msg(Arc::ERROR, "Schema validation error");
00224                     logger.msg(Arc::ERROR, err_msg);
00225                     exit(1);
00226                 }
00227             }
00228 
00229             // dump config if it was requested
00230             if (options.config_dump == true) {
00231                 std::string str;
00232                 config.GetXML(str, true);
00233                 std::cout << Arc::strip(str) << std::endl;
00234                 exit(0);
00235             }
00236 
00237             if (options.version) {
00238                 std::cout << Arc::IString("%s version %s", "arched", VERSION) << std::endl;
00239                 exit(0);
00240             }
00241 
00242             if(!MatchXMLName(config,"ArcConfig")) {
00243                 logger.msg(Arc::ERROR, "Configuration root element is not <ArcConfig>");
00244                 exit(1);
00245             }
00246 
00247             /* overwrite config variables by cmdline options */
00248             merge_options_and_config(config, options);
00249             std::string pid_file = (config["Server"]["PidFile"] ? (std::string)config["Server"]["PidFile"] : "/var/run/arched.pid");
00250             /* initalize logger infrastucture */
00251             std::string root_log_file = init_logger(config["Server"]["Logger"], config["Server"]["Foreground"]);
00252             std::string user = (std::string)config["Server"]["User"];
00253             std::string group = (std::string)config["Server"]["Group"];
00254             // set signal handlers
00255             signal(SIGTERM, shutdown);
00256             signal(SIGINT, shutdown);
00257 
00258             // switch user
00259             if (getuid() == 0) { // are we root?
00260                 /* switch group it is specified */
00261                 if (!group.empty()) {
00262                     gid_t g = get_gid(group);
00263                     if (setgid(g) != 0) {
00264                         logger.msg(Arc::ERROR, "Cannot switch to group (%s)", group);
00265                         exit(1);
00266                     }
00267                 }
00268                 /* switch user if it is specied */
00269                 if (!user.empty()) {
00270                     uid_t u = get_uid(user);
00271                     if (setuid(u) != 0) {
00272                         logger.msg(Arc::ERROR, "Cannot switch to user (%s)", user);
00273                         exit(1);
00274                     }
00275                 }
00276             }
00277             // demonize if the foreground options was not set
00278             if (!(bool)(config)["Server"]["Foreground"]) {
00279                 main_daemon = new Arc::Daemon(pid_file, root_log_file);
00280             }
00281 
00282             // bootstrap
00283             loader = new Arc::MCCLoader(config);
00284             if(!*loader) {
00285                 logger.msg(Arc::ERROR, "Failed to load service side MCCs");
00286             } else {
00287                 logger.msg(Arc::INFO, "Service side MCCs are loaded");
00288                 // sleep forever
00289                 for (;;) {
00290                     sleep(INT_MAX);
00291                 }
00292             }
00293         } else {
00294             logger.msg(Arc::ERROR, "Unexpected arguments supplied");
00295         }
00296     } catch (const Glib::Error& error) {
00297       logger.msg(Arc::ERROR, error.what());
00298     }
00299 
00300     exit_code = -1;
00301     shutdown(0);
00302     return exit_code;
00303 }