if [ "$DOWIN" = "yes" ]; then
version=`./configure --version | head -1 | awk '{ print $3 }'` \
|| error_cleanup "Cannot determine version number."
- version=`echo $version | sed -e 's/rc.*$//' -e 's/_20.*$//'`
if [ "$RC" != "no" -o "$SNAPSHOT" != "no" ]; then
if [ "$RC" != "no" ]; then
- version2=`echo $version | sed -e 's/rc.*//'`"rc$RC"
+ version2=`echo $version | sed -e 's/rc.*$//' -e 's/_20.*$//'`
+ version2=`echo $version2 | sed -e 's/rc.*//'`"rc$RC"
fi
if [ "$SNAPSHOT" != "no" ]; then
- version2="${version}_`date +%Y%m%d`"
+ version2=`echo $version | sed -e 's/rc.*$//' -e 's/_20.*$//'`
+ version2="${version2}_`date +%Y%m%d`"
fi
replace_text "configure.ac" "AC_INIT(unbound, $version" "AC_INIT(unbound, $version2"
version="$version2"
echo './configure --enable-debug --enable-static-exe "--with-conf-file=C:\Program Files\Unbound\service.conf" --with-run-dir="" --with-pidfile="" --with-chroot-dir="" '"$*"
./configure --enable-debug --enable-static-exe \
"--with-conf-file=C:\Program Files\Unbound\service.conf" \
- "--with-run-dir=C:\Program Files\Unbound" --with-pidfile="" \
- --with-chroot-dir="" $* \
+ --with-run-dir="" --with-pidfile="" --with-chroot-dir="" $* \
|| error_cleanup "Could not configure"
info "Calling make"
make || error_cleanup "Could not make"
# define LOG_INFO 6
# define LOG_DEBUG 7
#endif
+#ifdef UB_ON_WINDOWS
+# include "winrc/win_svc.h"
+#endif
/* default verbosity */
enum verbosity_value verbosity = 0;
static ub_thread_key_t logkey;
/** the identity of this executable/process */
static const char* ident="unbound";
-#ifdef HAVE_SYSLOG_H
+#if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)
/** are we using syslog(3) to log to */
static int logging_to_syslog = 0;
#endif /* HAVE_SYSLOG_H */
ub_thread_key_create(&logkey, NULL);
}
if(logfile
-#ifdef HAVE_SYSLOG_H
+#if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)
|| logging_to_syslog
#endif
)
logging_to_syslog = 1;
return;
}
+#elif defined(UB_ON_WINDOWS)
+ if(logging_to_syslog) {
+ logging_to_syslog = 0;
+ }
+ if(use_syslog) {
+ logging_to_syslog = 1;
+ return;
+ }
#endif /* HAVE_SYSLOG_H */
if(!filename || !filename[0]) {
logfile = stderr;
(int)getpid(), tid?*tid:0, type, message);
return;
}
+#elif defined(UB_ON_WINDOWS)
+ if(logging_to_syslog) {
+ char m[32768];
+ HANDLE* s;
+ LPCTSTR str = m;
+ DWORD tp = MSG_GENERIC_ERR;
+ WORD wt = EVENTLOG_ERROR_TYPE;
+ if(strcmp(type, "info") == 0) {
+ tp=MSG_GENERIC_INFO;
+ wt=EVENTLOG_INFORMATION_TYPE;
+ } else if(strcmp(type, "warning") == 0) {
+ tp=MSG_GENERIC_WARN;
+ wt=EVENTLOG_WARNING_TYPE;
+ } else if(strcmp(type, "notice") == 0
+ || strcmp(type, "debug") == 0) {
+ tp=MSG_GENERIC_SUCCESS;
+ wt=EVENTLOG_SUCCESS;
+ }
+ snprintf(m, sizeof(m), "[unbound:%x] %s: %s",
+ tid?*tid:0, type, message);
+ s = RegisterEventSource(NULL, SERVICE_NAME);
+ if(!s) return;
+ ReportEvent(s, wt, 0, tp, NULL, 1, 0, &str, NULL);
+ DeregisterEventSource(s);
+ return;
+ }
#endif /* HAVE_SYSLOG_H */
if(!logfile) return;
if(log_now)
#include "util/netevent.h"
#include "util/winsock_event.h"
-/** from gen_msg.h - success message record for windows message log */
-#define MSG_GENERIC_SUCCESS ((DWORD)0x20010001L)
-/** from gen_msg.h - informational message record for windows message log */
-#define MSG_GENERIC_INFO ((DWORD)0x60010002L)
-/** from gen_msg.h - warning message record for windows message log */
-#define MSG_GENERIC_WARN ((DWORD)0xA0010003L)
-/** from gen_msg.h - error message record for windows message log */
-#define MSG_GENERIC_ERR ((DWORD)0xE0010004L)
-
/** global service status */
SERVICE_STATUS service_status;
/** global service status handle */
/** event struct for stop callbacks */
struct event service_stop_ev;
/** config file to open. global communication to service_main() */
-const char* service_cfgfile = CONFIGFILE;
+char* service_cfgfile = CONFIGFILE;
/** commandline verbosity. global communication to service_main() */
int service_cmdline_verbose = 0;
* @param exitcode: error code (when stopped)
* @param wait: pending operation estimated time in milliseconds.
*/
-void report_status(DWORD state, DWORD exitcode, DWORD wait)
+static void report_status(DWORD state, DWORD exitcode, DWORD wait)
{
static DWORD checkpoint = 1;
service_status.dwCurrentState = state;
DeregisterEventSource(s);
}
+/**
+ * Obtain registry string (if it exists).
+ * @param key: key string
+ * @param name: name of value to fetch.
+ * @return malloced string with the result or NULL if it did not
+ * exist on an error (logged) was encountered.
+ */
+static char*
+lookup_reg_str(const char* key, const char* name)
+{
+ HKEY hk = NULL;
+ DWORD type = 0;
+ BYTE buf[1024];
+ DWORD len = (DWORD)sizeof(buf);
+ LONG ret;
+ char* result = NULL;
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hk);
+ if(ret == ERROR_FILE_NOT_FOUND)
+ return NULL; /* key does not exist */
+ else if(ret != ERROR_SUCCESS) {
+ reportev("RegOpenKeyEx failed");
+ return NULL;
+ }
+ ret = RegQueryValueEx(hk, (LPCTSTR)name, 0, &type, buf, &len);
+ if(RegCloseKey(hk))
+ reportev("RegCloseKey");
+ if(ret == ERROR_FILE_NOT_FOUND)
+ return NULL; /* name does not exist */
+ else if(ret != ERROR_SUCCESS) {
+ reportev("RegQueryValueEx failed");
+ return NULL;
+ }
+ if(type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ) {
+ buf[sizeof(buf)-1] = 0;
+ buf[sizeof(buf)-2] = 0; /* for multi_sz */
+ result = strdup(buf);
+ if(!result) reportev("out of memory");
+ }
+ return result;
+}
+
/**
* Init service. Keeps calling status pending to tell service control
* manager that this process is not hanging.
{
struct config_file* cfg = NULL;
struct daemon* daemon = NULL;
- const char* logfile= "C:\\unbound.log";
- verbosity=4; service_cmdline_verbose=4;
- log_init(logfile, 0, NULL); /* DEBUG logfile */
+
+ 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 */
daemon = daemon_init();
} else
verbose(VERB_QUERY, "chdir to %s", cfg->directory);
}
- /* log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); DEBUG*/
+ log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
report_status(SERVICE_START_PENDING, NO_ERROR, 2400);
verbose(VERB_QUERY, "winservice - apply cfg");
daemon_apply_cfg(daemon, cfg);
struct config_file* cfg = NULL;
struct daemon* daemon = NULL;
- reportev("Trying to report event");
-
service_status_handle = RegisterServiceCtrlHandler(SERVICE_NAME,
(LPHANDLER_FUNCTION)hdlr);
if(!service_status_handle) {
config_delete(cfg);
daemon_delete(daemon);
(void)WSACloseEvent(service_stop_event);
+ free(service_cfgfile);
verbose(VERB_QUERY, "winservice - full stop");
report_status(SERVICE_STOPPED, NO_ERROR, 0);
}
/** start the service */
static void
-service_start(const char* cfgfile, int v)
+service_start(const char* cfgfile, int v, int c)
{
SERVICE_TABLE_ENTRY myservices[2] = {
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main},
{NULL, NULL} };
verbosity=v;
- if(1) {
- /* DEBUG log to file */
+ if(verbosity >= VERB_QUERY) {
+ /* log to file about start sequence */
fclose(fopen("C:\\unbound.log", "w"));
log_init("C:\\unbound.log", 0, 0);
verbose(VERB_QUERY, "open logfile");
- }
- service_cfgfile = cfgfile;
+ } else log_init(0, 1, 0); /* otherwise, use Application log */
+ if(c) {
+ service_cfgfile = strdup(cfgfile);
+ if(!service_cfgfile) fatal_exit("out of memory");
+ } else service_cfgfile = NULL;
service_cmdline_verbose = v;
/* this call returns when service has stopped. */
if(!StartServiceCtrlDispatcher(myservices)) {
}
void
-wsvc_command_option(const char* wopt, const char* cfgfile, int v)
+wsvc_command_option(const char* wopt, const char* cfgfile, int v, int c)
{
if(strcmp(wopt, "install") == 0)
wsvc_install(stdout, NULL);
else if(strcmp(wopt, "remove") == 0)
wsvc_remove(stdout);
else if(strcmp(wopt, "service") == 0)
- service_start(cfgfile, v);
+ service_start(cfgfile, v, c);
else fatal_exit("unknown option: %s", wopt);
exit(0);
}