/** * Deinit the service */ static void service_deinit(struct daemon* daemon, struct config_file* cfg) { daemon_cleanup(daemon); config_delete(cfg); daemon_delete(daemon); }
/** * Run the daemon. * @param cfgfile: the config file name. * @param cmdline_verbose: verbosity resulting from commandline -v. * These increase verbosity as specified in the config file. * @param debug_mode: if set, do not daemonize. * @param log_default_identity: Default identity to report in logs */ static void run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity) { struct config_file* cfg = NULL; struct daemon* daemon = NULL; int done_setup = 0; if(!(daemon = daemon_init())) fatal_exit("alloc failure"); while(!daemon->need_to_exit) { if(done_setup) verbose(VERB_OPS, "Restart of %s.", PACKAGE_STRING); else verbose(VERB_OPS, "Start of %s.", PACKAGE_STRING); /* config stuff */ if(!(cfg = config_create())) fatal_exit("Could not alloc config defaults"); if(!config_read(cfg, cfgfile, daemon->chroot)) { if(errno != ENOENT) fatal_exit("Could not read config file: %s", cfgfile); log_warn("Continuing with default config settings"); } apply_settings(daemon, cfg, cmdline_verbose, debug_mode, log_default_identity); if(!done_setup) config_lookup_uid(cfg); /* prepare */ if(!daemon_open_shared_ports(daemon)) fatal_exit("could not open ports"); if(!done_setup) { perform_setup(daemon, cfg, debug_mode, &cfgfile); done_setup = 1; } else { /* reopen log after HUP to facilitate log rotation */ if(!cfg->use_syslog) log_init(cfg->logfile, 0, cfg->chrootdir); } /* work */ daemon_fork(daemon); /* clean up for restart */ verbose(VERB_ALGO, "cleanup."); daemon_cleanup(daemon); config_delete(cfg); } verbose(VERB_ALGO, "Exit cleanup."); /* this unlink may not work if the pidfile is located outside * of the chroot/workdir or we no longer have permissions */ if(daemon->pidfile) { int fd; /* truncate pidfile */ fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644); if(fd != -1) close(fd); /* delete pidfile */ unlink(daemon->pidfile); } daemon_delete(daemon); }
/** * Init service. Keeps calling status pending to tell service control * manager that this process is not hanging. * @param r: restart, true on restart * @param d: daemon returned here. * @param c: config file returned here. * @return false if failed. */ static int service_init(int r, struct daemon** d, struct config_file** c) { struct config_file* cfg = NULL; struct daemon* daemon = NULL; if(!service_cfgfile) { char* newf = lookup_reg_str("Software\\Unbound", "ConfigFile"); if(newf) service_cfgfile = newf; else service_cfgfile = strdup(CONFIGFILE); if(!service_cfgfile) fatal_exit("out of memory"); } /* create daemon */ if(r) daemon = *d; else daemon = daemon_init(); if(!daemon) return 0; if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2800); /* read config */ cfg = config_create(); if(!cfg) return 0; if(!config_read(cfg, service_cfgfile, daemon->chroot)) { if(errno != ENOENT) { log_err("error in config file"); return 0; } log_warn("could not open config file, using defaults"); } if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2600); verbose(VERB_QUERY, "winservice - apply settings"); /* apply settings and init */ verbosity = cfg->verbosity + service_cmdline_verbose; if(cfg->directory && cfg->directory[0]) { if(chdir(cfg->directory)) { log_err("could not chdir to %s: %s", cfg->directory, strerror(errno)); if(errno != ENOENT) return 0; log_warn("could not change directory - continuing"); } else verbose(VERB_QUERY, "chdir to %s", cfg->directory); } log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2400); verbose(VERB_QUERY, "winservice - apply cfg"); daemon_apply_cfg(daemon, cfg); if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2300); if(!(daemon->rc = daemon_remote_create(cfg))) { log_err("could not set up remote-control"); daemon_delete(daemon); config_delete(cfg); return 0; } /* open ports */ /* keep reporting that we are busy starting */ if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2200); verbose(VERB_QUERY, "winservice - open ports"); if(!daemon_open_shared_ports(daemon)) return 0; verbose(VERB_QUERY, "winservice - ports opened"); if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2000); *d = daemon; *c = cfg; return 1; }