From: Sean Campbell Date: Fri, 27 Jul 2018 13:21:03 +0000 (-0400) Subject: Base port to Windows (#2810) X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=df135922b19890047ebf725e6b82cd1c174c6d52;ds=sidebyside Base port to Windows (#2810) * Update configure.ac / Makefile.am to build for Windows using Cygwin. * Update build.sh to build for Windows. * Base port of the daemon. * Include gnulib as a submodule. --- diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..009ae439 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "gnulib"] + path = gnulib + url = git://git.savannah.gnu.org/gnulib.git diff --git a/Makefile.am b/Makefile.am index 4d32f74c..cb401487 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,13 @@ ACLOCAL_AMFLAGS = -I m4 AM_YFLAGS = -d +if BUILD_WIN32 +pkgdatadir=$(datadir) +pkglibdir=$(libdir)/plugins +pkglocalstatedir=${localstatedir} +else +pkglocalstatedir=${localstatedir}/lib/${PACKAGE_NAME} +endif BUILT_SOURCES = \ src/libcollectdclient/collectd/lcc_features.h \ @@ -99,7 +106,13 @@ pkginclude_HEADERS = \ lib_LTLIBRARIES = libcollectdclient.la +if BUILD_WIN32 +# TODO: Build all executables on Windows as well. +sbin_PROGRAMS = \ + collectd +bin_PROGRAMS = +else sbin_PROGRAMS = \ collectd \ collectdmon @@ -109,9 +122,10 @@ bin_PROGRAMS = \ collectd-nagios \ collectd-tg \ collectdctl +endif # BUILD_WIN32 -noinst_LTLIBRARIES = \ +EXTRA_LTLIBRARIES = \ libavltree.la \ libcmds.la \ libcommon.la \ @@ -160,6 +174,9 @@ PLUGIN_LDFLAGS = \ -module \ -avoid-version \ -export-symbols-regex '\' +if BUILD_WIN32 +PLUGIN_LDFLAGS += -shared -no-undefined -lcollectd -L. +endif AM_CPPFLAGS = \ @@ -167,13 +184,26 @@ AM_CPPFLAGS = \ -DPREFIX='"${prefix}"' \ -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"' \ -DLOCALSTATEDIR='"${localstatedir}"' \ - -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"' \ + -DPKGLOCALSTATEDIR='"${pkglocalstatedir}"' \ -DPLUGINDIR='"${pkglibdir}"' \ -DPKGDATADIR='"${pkgdatadir}"' +if BUILD_WIN32 +AM_CPPFLAGS += -DNOGDI +endif +COMMON_DEPS = +if BUILD_WIN32 +COMMON_DEPS += collectd.exe +endif # Link to these libraries.. COMMON_LIBS = $(PTHREAD_LIBS) +if BUILD_WIN32 +COMMON_LIBS += -lws2_32 +endif +if BUILD_WITH_GNULIB +COMMON_LIBS += -lgnu +endif if BUILD_WITH_CAPABILITY COMMON_LIBS += -lcap endif @@ -195,7 +225,6 @@ endif collectd_SOURCES = \ - src/daemon/cmd.c \ src/daemon/cmd.h \ src/daemon/collectd.c \ src/daemon/collectd.h \ @@ -239,6 +268,13 @@ collectd_LDADD = \ $(COMMON_LIBS) \ $(DLOPEN_LIBS) +if BUILD_WIN32 +collectd_SOURCES += src/daemon/cmd_windows.c +collectd_LDFLAGS += -ldl -Wl,--out-implib,libcollectd.a +else +collectd_SOURCES += src/daemon/cmd.c +endif + if BUILD_FEATURE_DAEMON collectd_CPPFLAGS += -DPIDFILE='"${localstatedir}/run/${PACKAGE_NAME}.pid"' endif @@ -250,6 +286,9 @@ collectd_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) collectd_LDADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS) endif +if BUILD_WIN32 +collectd_LDFLAGS += -Wl,--out-implib,libcollectd.a +endif collectdmon_SOURCES = src/collectdmon.c @@ -501,6 +540,10 @@ libcollectdclient_la_CPPFLAGS = \ -I$(srcdir)/src/daemon libcollectdclient_la_LDFLAGS = -version-info 2:0:1 libcollectdclient_la_LIBADD = -lm +if BUILD_WIN32 +libcollectdclient_la_LDFLAGS += -shared -no-undefined +libcollectdclient_la_LIBADD += -lgnu -lws2_32 -liphlpapi +endif if BUILD_WITH_LIBGCRYPT libcollectdclient_la_CPPFLAGS += $(GCRYPT_CPPFLAGS) libcollectdclient_la_LDFLAGS += $(GCRYPT_LDFLAGS) @@ -1042,6 +1085,7 @@ if BUILD_PLUGIN_LOGFILE pkglib_LTLIBRARIES += logfile.la logfile_la_SOURCES = src/logfile.c logfile_la_LDFLAGS = $(PLUGIN_LDFLAGS) +logfile_la_DEPENDENCIES = $(COMMON_DEPS) endif if BUILD_PLUGIN_LOG_LOGSTASH @@ -1471,7 +1515,7 @@ python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBPYTHON_LDFLAGS) endif if HAVE_LIBMNL -noinst_LTLIBRARIES += libtaskstats.la +EXTRA_LTLIBRARIES += libtaskstats.la libtaskstats_la_SOURCES = \ src/utils_taskstats.c \ src/utils_taskstats.h @@ -2138,3 +2182,4 @@ generic-jmx.jar: $(JAVA_TIMESTAMP_FILE) jar_DATA = collectd-api.jar generic-jmx.jar endif + diff --git a/README b/README index a111e84a..a5947038 100644 --- a/README +++ b/README @@ -1044,6 +1044,37 @@ To generate the `configure` script, you'll need the following dependencies: The `build.sh' script takes no arguments. +Building on Windows +----------------------------------------------- + +Collectd can be built on Windows using Cygwin, and the result is a binary that +runs natively on Windows. That is, Cygwin is only needed for building, not running, +collectd. + +You will need to install the following Cygwin packages: +- automake +- bison +- flex +- git +- libtool +- make +- mingw64-x86_64-dlfcn +- mingw64-x86_64-gcc-core +- mingw64-x86_64-zlib +- pkg-config + +To build, just run the `build.sh' script in your Cygwin terminal. By default, it installs +to "C:/Program Files/collectd". You can change the location by setting the INSTALL_DIR +variable: + +$ export INSTALL_DIR="C:/some/other/install/directory" +$ ./build.sh + +or: + +$ INSTALL_DIR="C:/some/other/install/directory" ./build.sh + + Crosscompiling -------------- diff --git a/build.sh b/build.sh index bd4c1a31..c7d557aa 100755 --- a/build.sh +++ b/build.sh @@ -18,34 +18,152 @@ EOF done } -check_for_application lex bison autoheader aclocal automake autoconf pkg-config - -libtoolize="" -libtoolize --version >/dev/null 2>/dev/null -if test $? -eq 0; then - libtoolize=libtoolize -else - glibtoolize --version >/dev/null 2>/dev/null +setup_libtool() +{ + libtoolize="" + libtoolize --version >/dev/null 2>/dev/null if test $? -eq 0; then - libtoolize=glibtoolize + libtoolize=libtoolize else - cat >&2 </dev/null 2>/dev/null + if test $? -eq 0; then + libtoolize=glibtoolize + else + cat >&2 <" >> src/gnulib_config.h + + cp libtool libtool_bak + sed -i "s%\$LTCC \$LTCFLAGS\(.*cwrapper.*\)%\$LTCC \1%" libtool + + make + make install + + cp "${GNULIB_DIR}/libgnu.dll" "${INSTALL_DIR}" + cp "${MINGW_ROOT}/bin/zlib1.dll" "${INSTALL_DIR}" + cp "${MINGW_ROOT}/bin/libwinpthread-1.dll" "${INSTALL_DIR}" + cp "${MINGW_ROOT}/bin/libdl.dll" "${INSTALL_DIR}" + + echo "Done." +} + +os_name="$(uname)" +if test "${os_name#CYGWIN}" != "$os_name"; then + build_cygwin +else + build +fi -autoheader \ -&& aclocal -I m4 \ -&& $libtoolize --copy --force \ -&& automake --add-missing --copy \ -&& autoconf diff --git a/configure.ac b/configure.ac index 54eb7f6f..36b66e53 100644 --- a/configure.ac +++ b/configure.ac @@ -99,6 +99,10 @@ case $host_os in AC_DEFINE([KERNEL_SOLARIS], [1], [True if program is to be compiled for a Solaris kernel]) ac_system="Solaris" ;; + *mingw32*) + AC_DEFINE([KERNEL_WIN32], [1], [True if program is to be compiled for a Windows kernel]) + ac_system="Windows" + ;; *) ac_system="unknown" ;; @@ -111,6 +115,7 @@ AM_CONDITIONAL([BUILD_FREEBSD], [test "x$ac_system" = "xFreeBSD"]) AM_CONDITIONAL([BUILD_LINUX], [test "x$ac_system" = "xLinux"]) AM_CONDITIONAL([BUILD_OPENBSD], [test "x$ac_system" = "xOpenBSD"]) AM_CONDITIONAL([BUILD_SOLARIS], [test "x$ac_system" = "xSolaris"]) +AM_CONDITIONAL([BUILD_WIN32], [test "x$ac_system" = "xWindows"]) if test "x$ac_system" = "xSolaris"; then AC_DEFINE([_POSIX_PTHREAD_SEMANTICS], [1], [Define to enforce POSIX thread semantics under Solaris.]) @@ -751,6 +756,7 @@ AC_CHECK_FUNCS_ONCE([ \ getaddrinfo \ getgrnam_r \ getnameinfo \ + getpwnam \ getpwnam_r \ gettimeofday \ if_indextoname \ @@ -857,11 +863,17 @@ AC_CHECK_FUNCS([socket], [ AC_CHECK_LIB([socket], [socket], [socket_needs_socket="yes"], - [AC_MSG_ERROR([cannot find socket() in libsocket])] + [ + AC_CHECK_LIB([gnu], [rpl_socket], + [socket_needs_gnulib="yes"], + [AC_MSG_ERROR([cannot find socket() in libsocket])] + ) + ] ) ] ) AM_CONDITIONAL([BUILD_WITH_LIBSOCKET], [test "x$socket_needs_socket" = "xyes"]) +AM_CONDITIONAL([BUILD_WITH_GNULIB], [test "x$socket_needs_gnulib" = "xyes"]) clock_gettime_needs_posix4="no" AC_CHECK_FUNCS([clock_gettime], @@ -7253,3 +7265,4 @@ if test "x$dependency_warning" = "xyes"; then fi # vim: set fdm=marker sw=2 sts=2 ts=2 et : + diff --git a/gnulib b/gnulib new file mode 160000 index 00000000..2f8140bc --- /dev/null +++ b/gnulib @@ -0,0 +1 @@ +Subproject commit 2f8140bc8ce5501e31dcc665b42b5df64f84c20c diff --git a/src/daemon/cmd_windows.c b/src/daemon/cmd_windows.c new file mode 100755 index 00000000..2542be51 --- /dev/null +++ b/src/daemon/cmd_windows.c @@ -0,0 +1,40 @@ +/** + * collectd - src/collectd_windows.c + * Copyright (C) 2017 Google LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + **/ + +#include "cmd.h" +#include "plugin.h" +#include +#include + +int main(int argc, char **argv) { + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(2, 2); + int err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + ERROR("WSAStartup failed with error: %d\n", err); + return 1; + } + + struct cmdline_config config = init_config(argc, argv); + return run_loop(config.test_readall); +} diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c index 0149f405..f1a49237 100644 --- a/src/daemon/collectd.c +++ b/src/daemon/collectd.c @@ -51,6 +51,14 @@ #define COLLECTD_LOCALE "C" #endif +#ifdef WIN32 +#undef COLLECT_DAEMON +#include +#undef gethostname +#include +#include +#endif + static int loop; static int init_hostname(void) { @@ -60,10 +68,14 @@ static int init_hostname(void) { return 0; } +#ifdef WIN32 + long hostname_len = NI_MAXHOST; +#else long hostname_len = sysconf(_SC_HOST_NAME_MAX); if (hostname_len == -1) { hostname_len = NI_MAXHOST; } +#endif /* WIN32 */ char hostname[hostname_len]; if (gethostname(hostname, hostname_len) != 0) { diff --git a/src/daemon/collectd.h b/src/daemon/collectd.h index 459da4dc..07597d3b 100644 --- a/src/daemon/collectd.h +++ b/src/daemon/collectd.h @@ -27,6 +27,11 @@ #ifndef COLLECTD_H #define COLLECTD_H +#ifdef WIN32 +typedef int uid_t; +#include "gnulib_config.h" +#endif + #if HAVE_CONFIG_H #include "config.h" #endif @@ -122,6 +127,10 @@ #include #endif +#if HAVE_SYS_PARAM_H +#include +#endif + #ifndef BYTE_ORDER #if defined(_BYTE_ORDER) #define BYTE_ORDER _BYTE_ORDER @@ -183,10 +192,6 @@ #endif #endif -#if HAVE_SYS_PARAM_H -#include -#endif - #ifndef PACKAGE_NAME #define PACKAGE_NAME "collectd" #endif diff --git a/src/daemon/common.c b/src/daemon/common.c index 76c7036d..99f48caf 100644 --- a/src/daemon/common.c +++ b/src/daemon/common.c @@ -27,10 +27,6 @@ * Michał Mirosław **/ -#if HAVE_CONFIG_H -#include "config.h" -#endif - #include "collectd.h" #include "common.h" @@ -68,12 +64,17 @@ extern kstat_ctl_t *kc; #endif +#if !defined(MSG_DONTWAIT) +#if defined(MSG_NONBLOCK) /* AIX doesn't have MSG_DONTWAIT */ -#ifndef MSG_DONTWAIT #define MSG_DONTWAIT MSG_NONBLOCK -#endif +#else +/* Windows doesn't have MSG_DONTWAIT or MSG_NONBLOCK */ +#define MSG_DONTWAIT 0 +#endif /* defined(MSG_NONBLOCK) */ +#endif /* !defined(MSG_DONTWAIT) */ -#if !HAVE_GETPWNAM_R +#if !HAVE_GETPWNAM_R && defined(HAVE_GETPWNAM) static pthread_mutex_t getpwnam_r_lock = PTHREAD_MUTEX_INITIALIZER; #endif @@ -1132,6 +1133,9 @@ int parse_value_file(char const *path, value_t *ret_value, int ds_type) { #if !HAVE_GETPWNAM_R int getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) { +#ifndef HAVE_GETPWNAM + return -1; +#else int status = 0; struct passwd *pw; @@ -1174,6 +1178,7 @@ int getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, pthread_mutex_unlock(&getpwnam_r_lock); return status; +#endif /* HAVE_GETPWNAM */ } /* int getpwnam_r */ #endif /* !HAVE_GETPWNAM_R */ diff --git a/src/daemon/common.h b/src/daemon/common.h index db1b4650..8cd4e22c 100644 --- a/src/daemon/common.h +++ b/src/daemon/common.h @@ -335,6 +335,7 @@ int parse_values(char *buffer, value_list_t *vl, const data_set_t *ds); int parse_value_file(char const *path, value_t *ret_value, int ds_type); #if !HAVE_GETPWNAM_R +struct passwd; int getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); #endif diff --git a/src/daemon/globals.h b/src/daemon/globals.h index 5a277c00..9ec72f0d 100644 --- a/src/daemon/globals.h +++ b/src/daemon/globals.h @@ -31,8 +31,12 @@ #endif #ifndef PRIsz +#ifdef WIN32 +#define PRIsz "Iu" +#else #define PRIsz "zu" -#endif /* PRIsz */ +#endif /* WIN32 */ +#endif /* !PRIsz */ /* Type for time as used by "utils_time.h" */ typedef uint64_t cdtime_t; diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c index 73d7c841..b93e9cc9 100644 --- a/src/daemon/plugin.c +++ b/src/daemon/plugin.c @@ -42,6 +42,14 @@ #include "utils_random.h" #include "utils_time.h" +#ifdef WIN32 +#define EXPORT __declspec(dllexport) +#include +#include +#else +#define EXPORT +#endif + #if HAVE_PTHREAD_NP_H #include /* for pthread_set_name_np(3) */ #endif @@ -640,7 +648,7 @@ static void start_read_threads(size_t num) /* {{{ */ } char name[THREAD_NAME_MAX]; - snprintf(name, sizeof(name), "reader#%" PRIsz, read_threads_num); + snprintf(name, sizeof(name), "reader#%" PRIu64, (uint64_t)read_threads_num); set_thread_name(read_threads[read_threads_num], name); read_threads_num++; @@ -829,7 +837,8 @@ static void start_write_threads(size_t num) /* {{{ */ } char name[THREAD_NAME_MAX]; - snprintf(name, sizeof(name), "writer#%" PRIsz, write_threads_num); + snprintf(name, sizeof(name), "writer#%" PRIu64, + (uint64_t)write_threads_num); set_thread_name(write_threads[write_threads_num], name); write_threads_num++; @@ -940,6 +949,11 @@ static void plugin_free_loaded(void) { } #define BUFSIZE 512 +#ifdef WIN32 +#define SHLIB_SUFFIX ".dll" +#else +#define SHLIB_SUFFIX ".so" +#endif int plugin_load(char const *plugin_name, bool global) { DIR *dh; const char *dir; @@ -976,11 +990,12 @@ int plugin_load(char const *plugin_name, bool global) { (strcasecmp("python", plugin_name) == 0)) global = true; - /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the + /* `cpu' should not match `cpufreq'. To solve this we add SHLIB_SUFFIX to the * type when matching the filename */ - status = snprintf(typename, sizeof(typename), "%s.so", plugin_name); + status = snprintf(typename, sizeof(typename), "%s" SHLIB_SUFFIX, plugin_name); if ((status < 0) || ((size_t)status >= sizeof(typename))) { - WARNING("plugin_load: Filename too long: \"%s.so\"", plugin_name); + WARNING("plugin_load: Filename too long: \"%s" SHLIB_SUFFIX "\"", + plugin_name); return -1; } @@ -1033,19 +1048,20 @@ int plugin_load(char const *plugin_name, bool global) { /* * The `register_*' functions follow */ -int plugin_register_config(const char *name, - int (*callback)(const char *key, const char *val), - const char **keys, int keys_num) { +EXPORT int plugin_register_config(const char *name, + int (*callback)(const char *key, + const char *val), + const char **keys, int keys_num) { cf_register(name, callback, keys, keys_num); return 0; } /* int plugin_register_config */ -int plugin_register_complex_config(const char *type, - int (*callback)(oconfig_item_t *)) { +EXPORT int plugin_register_complex_config(const char *type, + int (*callback)(oconfig_item_t *)) { return cf_register_complex(type, callback); } /* int plugin_register_complex_config */ -int plugin_register_init(const char *name, int (*callback)(void)) { +EXPORT int plugin_register_init(const char *name, int (*callback)(void)) { return create_register_callback(&list_init, name, (void *)callback, NULL); } /* plugin_register_init */ @@ -1127,7 +1143,7 @@ static int plugin_insert_read(read_func_t *rf) { return 0; } /* int plugin_insert_read */ -int plugin_register_read(const char *name, int (*callback)(void)) { +EXPORT int plugin_register_read(const char *name, int (*callback)(void)) { read_func_t *rf; int status; @@ -1156,9 +1172,10 @@ int plugin_register_read(const char *name, int (*callback)(void)) { return status; } /* int plugin_register_read */ -int plugin_register_complex_read(const char *group, const char *name, - plugin_read_cb callback, cdtime_t interval, - user_data_t const *user_data) { +EXPORT int plugin_register_complex_read(const char *group, const char *name, + plugin_read_cb callback, + cdtime_t interval, + user_data_t const *user_data) { read_func_t *rf; int status; @@ -1199,8 +1216,8 @@ int plugin_register_complex_read(const char *group, const char *name, return status; } /* int plugin_register_complex_read */ -int plugin_register_write(const char *name, plugin_write_cb callback, - user_data_t const *ud) { +EXPORT int plugin_register_write(const char *name, plugin_write_cb callback, + user_data_t const *ud) { return create_register_callback(&list_write, name, (void *)callback, ud); } /* int plugin_register_write */ @@ -1241,8 +1258,8 @@ static char *plugin_flush_callback_name(const char *name) { return flush_name; } /* static char *plugin_flush_callback_name */ -int plugin_register_flush(const char *name, plugin_flush_cb callback, - user_data_t const *ud) { +EXPORT int plugin_register_flush(const char *name, plugin_flush_cb callback, + user_data_t const *ud) { int status; plugin_ctx_t ctx = plugin_get_ctx(); @@ -1290,12 +1307,12 @@ int plugin_register_flush(const char *name, plugin_flush_cb callback, return 0; } /* int plugin_register_flush */ -int plugin_register_missing(const char *name, plugin_missing_cb callback, - user_data_t const *ud) { +EXPORT int plugin_register_missing(const char *name, plugin_missing_cb callback, + user_data_t const *ud) { return create_register_callback(&list_missing, name, (void *)callback, ud); } /* int plugin_register_missing */ -int plugin_register_shutdown(const char *name, int (*callback)(void)) { +EXPORT int plugin_register_shutdown(const char *name, int (*callback)(void)) { return create_register_callback(&list_shutdown, name, (void *)callback, NULL); } /* int plugin_register_shutdown */ @@ -1318,7 +1335,7 @@ static void plugin_free_data_sets(void) { data_sets = NULL; } /* void plugin_free_data_sets */ -int plugin_register_data_set(const data_set_t *ds) { +EXPORT int plugin_register_data_set(const data_set_t *ds) { data_set_t *ds_copy; if ((data_sets != NULL) && (c_avl_get(data_sets, ds->type, NULL) == 0)) { @@ -1347,33 +1364,33 @@ int plugin_register_data_set(const data_set_t *ds) { return c_avl_insert(data_sets, (void *)ds_copy->type, (void *)ds_copy); } /* int plugin_register_data_set */ -int plugin_register_log(const char *name, plugin_log_cb callback, - user_data_t const *ud) { +EXPORT int plugin_register_log(const char *name, plugin_log_cb callback, + user_data_t const *ud) { return create_register_callback(&list_log, name, (void *)callback, ud); } /* int plugin_register_log */ -int plugin_register_notification(const char *name, - plugin_notification_cb callback, - user_data_t const *ud) { +EXPORT int plugin_register_notification(const char *name, + plugin_notification_cb callback, + user_data_t const *ud) { return create_register_callback(&list_notification, name, (void *)callback, ud); } /* int plugin_register_log */ -int plugin_unregister_config(const char *name) { +EXPORT int plugin_unregister_config(const char *name) { cf_unregister(name); return 0; } /* int plugin_unregister_config */ -int plugin_unregister_complex_config(const char *name) { +EXPORT int plugin_unregister_complex_config(const char *name) { cf_unregister_complex(name); return 0; } /* int plugin_unregister_complex_config */ -int plugin_unregister_init(const char *name) { +EXPORT int plugin_unregister_init(const char *name) { return plugin_unregister(list_init, name); } -int plugin_unregister_read(const char *name) /* {{{ */ +EXPORT int plugin_unregister_read(const char *name) /* {{{ */ { llentry_t *le; read_func_t *rf; @@ -1410,7 +1427,7 @@ int plugin_unregister_read(const char *name) /* {{{ */ return 0; } /* }}} int plugin_unregister_read */ -void plugin_log_available_writers(void) { +EXPORT void plugin_log_available_writers(void) { log_list_callbacks(&list_write, "Available write targets:"); } @@ -1422,7 +1439,7 @@ static int compare_read_func_group(llentry_t *e, void *ud) /* {{{ */ return strcmp(rf->rf_group, (const char *)group); } /* }}} int compare_read_func_group */ -int plugin_unregister_read_group(const char *group) /* {{{ */ +EXPORT int plugin_unregister_read_group(const char *group) /* {{{ */ { llentry_t *le; read_func_t *rf; @@ -1472,11 +1489,11 @@ int plugin_unregister_read_group(const char *group) /* {{{ */ return 0; } /* }}} int plugin_unregister_read_group */ -int plugin_unregister_write(const char *name) { +EXPORT int plugin_unregister_write(const char *name) { return plugin_unregister(list_write, name); } -int plugin_unregister_flush(const char *name) { +EXPORT int plugin_unregister_flush(const char *name) { plugin_ctx_t ctx = plugin_get_ctx(); if (ctx.flush_interval != 0) { @@ -1492,15 +1509,15 @@ int plugin_unregister_flush(const char *name) { return plugin_unregister(list_flush, name); } -int plugin_unregister_missing(const char *name) { +EXPORT int plugin_unregister_missing(const char *name) { return plugin_unregister(list_missing, name); } -int plugin_unregister_shutdown(const char *name) { +EXPORT int plugin_unregister_shutdown(const char *name) { return plugin_unregister(list_shutdown, name); } -int plugin_unregister_data_set(const char *name) { +EXPORT int plugin_unregister_data_set(const char *name) { data_set_t *ds; if (data_sets == NULL) @@ -1515,15 +1532,15 @@ int plugin_unregister_data_set(const char *name) { return 0; } /* int plugin_unregister_data_set */ -int plugin_unregister_log(const char *name) { +EXPORT int plugin_unregister_log(const char *name) { return plugin_unregister(list_log, name); } -int plugin_unregister_notification(const char *name) { +EXPORT int plugin_unregister_notification(const char *name) { return plugin_unregister(list_notification, name); } -int plugin_init_all(void) { +EXPORT int plugin_init_all(void) { char const *chain_name; llentry_t *le; int status; @@ -1622,14 +1639,14 @@ int plugin_init_all(void) { } /* void plugin_init_all */ /* TODO: Rename this function. */ -void plugin_read_all(void) { +EXPORT void plugin_read_all(void) { uc_check_timeout(); return; } /* void plugin_read_all */ /* Read function called when the `-T' command line argument is given. */ -int plugin_read_all_once(void) { +EXPORT int plugin_read_all_once(void) { int status; int return_status = 0; @@ -1674,8 +1691,8 @@ int plugin_read_all_once(void) { return return_status; } /* int plugin_read_all_once */ -int plugin_write(const char *plugin, /* {{{ */ - const data_set_t *ds, const value_list_t *vl) { +EXPORT int plugin_write(const char *plugin, /* {{{ */ + const data_set_t *ds, const value_list_t *vl) { llentry_t *le; int status; @@ -1754,7 +1771,8 @@ int plugin_write(const char *plugin, /* {{{ */ return status; } /* }}} int plugin_write */ -int plugin_flush(const char *plugin, cdtime_t timeout, const char *identifier) { +EXPORT int plugin_flush(const char *plugin, cdtime_t timeout, + const char *identifier) { llentry_t *le; if (list_flush == NULL) @@ -1784,7 +1802,7 @@ int plugin_flush(const char *plugin, cdtime_t timeout, const char *identifier) { return 0; } /* int plugin_flush */ -int plugin_shutdown_all(void) { +EXPORT int plugin_shutdown_all(void) { llentry_t *le; int ret = 0; // Assume success. @@ -1850,7 +1868,7 @@ int plugin_shutdown_all(void) { return ret; } /* void plugin_shutdown_all */ -int plugin_dispatch_missing(const value_list_t *vl) /* {{{ */ +EXPORT int plugin_dispatch_missing(const value_list_t *vl) /* {{{ */ { if (list_missing == NULL) return 0; @@ -2056,7 +2074,7 @@ static bool check_drop_value(void) /* {{{ */ return false; } /* }}} bool check_drop_value */ -int plugin_dispatch_values(value_list_t const *vl) { +EXPORT int plugin_dispatch_values(value_list_t const *vl) { int status; static pthread_mutex_t statistics_lock = PTHREAD_MUTEX_INITIALIZER; @@ -2155,7 +2173,7 @@ plugin_dispatch_multivalue(value_list_t const *template, /* {{{ */ return failed; } /* }}} int plugin_dispatch_multivalue */ -int plugin_dispatch_notification(const notification_t *notif) { +EXPORT int plugin_dispatch_notification(const notification_t *notif) { llentry_t *le; /* Possible TODO: Add flap detection here */ @@ -2192,7 +2210,7 @@ int plugin_dispatch_notification(const notification_t *notif) { return 0; } /* int plugin_dispatch_notification */ -void plugin_log(int level, const char *format, ...) { +EXPORT void plugin_log(int level, const char *format, ...) { char msg[1024]; va_list ap; llentry_t *le; @@ -2265,7 +2283,7 @@ int parse_log_severity(const char *severity) { return log_level; } /* int parse_log_severity */ -int parse_notif_severity(const char *severity) { +EXPORT int parse_notif_severity(const char *severity) { int notif_severity = -1; if (strcasecmp(severity, "FAILURE") == 0) @@ -2279,7 +2297,7 @@ int parse_notif_severity(const char *severity) { return notif_severity; } /* int parse_notif_severity */ -const data_set_t *plugin_get_ds(const char *name) { +EXPORT const data_set_t *plugin_get_ds(const char *name) { data_set_t *ds; if (data_sets == NULL) { @@ -2466,12 +2484,12 @@ static plugin_ctx_t *plugin_ctx_create(void) { return ctx; } /* int plugin_ctx_create */ -void plugin_init_ctx(void) { +EXPORT void plugin_init_ctx(void) { pthread_key_create(&plugin_ctx_key, plugin_ctx_destructor); plugin_ctx_key_initialized = true; } /* void plugin_init_ctx */ -plugin_ctx_t plugin_get_ctx(void) { +EXPORT plugin_ctx_t plugin_get_ctx(void) { plugin_ctx_t *ctx; assert(plugin_ctx_key_initialized); @@ -2487,7 +2505,7 @@ plugin_ctx_t plugin_get_ctx(void) { return *ctx; } /* plugin_ctx_t plugin_get_ctx */ -plugin_ctx_t plugin_set_ctx(plugin_ctx_t ctx) { +EXPORT plugin_ctx_t plugin_set_ctx(plugin_ctx_t ctx) { plugin_ctx_t *c; plugin_ctx_t old; @@ -2507,7 +2525,7 @@ plugin_ctx_t plugin_set_ctx(plugin_ctx_t ctx) { return old; } /* void plugin_set_ctx */ -cdtime_t plugin_get_interval(void) { +EXPORT cdtime_t plugin_get_interval(void) { cdtime_t interval; interval = plugin_get_ctx().interval; diff --git a/src/daemon/plugin.h b/src/daemon/plugin.h index 871eccdc..2d903cb6 100644 --- a/src/daemon/plugin.h +++ b/src/daemon/plugin.h @@ -34,6 +34,7 @@ #include "meta_data.h" #include "utils_time.h" +#include #include #define DS_TYPE_COUNTER 0 diff --git a/src/daemon/utils_heap.c b/src/daemon/utils_heap.c index d36d410b..3cecd893 100644 --- a/src/daemon/utils_heap.c +++ b/src/daemon/utils_heap.c @@ -24,6 +24,8 @@ * Florian octo Forster **/ +#include "collectd.h" + #include #include #include diff --git a/src/daemon/utils_random.c b/src/daemon/utils_random.c index 7a9ce7be..5500aaa0 100644 --- a/src/daemon/utils_random.c +++ b/src/daemon/utils_random.c @@ -31,6 +31,14 @@ #include +#ifdef WIN32 +double erand48(unsigned short unused[3]) { + return (double)rand() / (double)RAND_MAX; +} + +long int jrand48(unsigned short unused[3]) { return rand(); } +#endif + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static bool have_seed; static unsigned short seed[3]; @@ -47,6 +55,10 @@ static void cdrand_seed(void) { seed[1] = (unsigned short)(t >> 16); seed[2] = (unsigned short)(t >> 32); +#ifdef WIN32 + srand((unsigned)t); +#endif + have_seed = true; } diff --git a/src/libcollectdclient/client.c b/src/libcollectdclient/client.c index d4703245..df6fd960 100644 --- a/src/libcollectdclient/client.c +++ b/src/libcollectdclient/client.c @@ -24,6 +24,11 @@ * Florian octo Forster **/ +#ifdef WIN32 +#include "gnulib_config.h" +#include +#endif + #include "config.h" #if !defined(__GNUC__) || !__GNUC__ @@ -40,11 +45,14 @@ #include #include #include -#include #include -#include #include +#ifndef WIN32 +#include +#include +#endif + #include "collectd/client.h" /* NI_MAXHOST has been obsoleted by RFC 3493 which is a reason for SunOS 5.11 @@ -62,6 +70,10 @@ #endif #endif +#ifdef WIN32 +#define AI_ADDRCONFIG 0 +#endif + /* Secure/static macros. They work like `strcpy' and `strcat', but assure null * termination. They work for static buffers only, because they use `sizeof'. * The `SSTRCATF' combines the functionality of `snprintf' and `strcat' which @@ -367,6 +379,10 @@ static int lcc_sendreceive(lcc_connection_t *c, /* {{{ */ static int lcc_open_unixsocket(lcc_connection_t *c, const char *path) /* {{{ */ { +#ifdef WIN32 + lcc_set_errno(c, ENOTSUP); + return -1; +#else struct sockaddr_un sa = {0}; int fd; int status; @@ -401,6 +417,7 @@ static int lcc_open_unixsocket(lcc_connection_t *c, const char *path) /* {{{ */ } return 0; +#endif /* WIN32 */ } /* }}} int lcc_open_unixsocket */ static int lcc_open_netsocket(lcc_connection_t *c, /* {{{ */ diff --git a/src/libcollectdclient/collectd/network.h b/src/libcollectdclient/collectd/network.h index c8a5da54..0b973620 100644 --- a/src/libcollectdclient/collectd/network.h +++ b/src/libcollectdclient/collectd/network.h @@ -32,6 +32,10 @@ #include #include +#ifdef WIN32 +extern unsigned int if_nametoindex(const char *interface_name); +#endif + #define NET_DEFAULT_V4_ADDR "239.192.74.66" #define NET_DEFAULT_V6_ADDR "ff18::efc0:4a42" #define NET_DEFAULT_PORT "25826" @@ -60,7 +64,7 @@ int lcc_server_destroy(lcc_network_t *net, lcc_server_t *srv); /* Configure servers */ int lcc_server_set_ttl(lcc_server_t *srv, uint8_t ttl); -int lcc_server_set_interface(lcc_server_t *srv, char const *interface); +int lcc_server_set_interface(lcc_server_t *srv, char const *iface); int lcc_server_set_security_level(lcc_server_t *srv, lcc_security_level_t level, const char *username, const char *password); diff --git a/src/libcollectdclient/collectd/server.h b/src/libcollectdclient/collectd/server.h index ef6b792b..e50df17d 100644 --- a/src/libcollectdclient/collectd/server.h +++ b/src/libcollectdclient/collectd/server.h @@ -74,7 +74,7 @@ typedef struct { /* interface is the name of the interface to use when subscribing to a * multicast group. Has no effect when using unicast. */ - char *interface; + char *iface; } lcc_listener_t; /* lcc_listen_and_write listens on the provided UDP socket (or opens one using diff --git a/src/libcollectdclient/network.c b/src/libcollectdclient/network.c index 49257d4a..2d6b3ed4 100644 --- a/src/libcollectdclient/network.c +++ b/src/libcollectdclient/network.c @@ -47,6 +47,10 @@ #include #endif +#ifdef WIN32 +#define AI_ADDRCONFIG 0 +#endif + #include "collectd/network.h" #include "collectd/network_buffer.h" @@ -364,15 +368,15 @@ int lcc_server_set_ttl(lcc_server_t *srv, uint8_t ttl) /* {{{ */ return 0; } /* }}} int lcc_server_set_ttl */ -int lcc_server_set_interface(lcc_server_t *srv, char const *interface) /* {{{ */ +int lcc_server_set_interface(lcc_server_t *srv, char const *iface) /* {{{ */ { unsigned int if_index; int status; - if ((srv == NULL) || (interface == NULL)) + if ((srv == NULL) || (iface == NULL)) return EINVAL; - if_index = if_nametoindex(interface); + if_index = if_nametoindex(iface); if (if_index == 0) return ENOENT; @@ -420,8 +424,8 @@ int lcc_server_set_interface(lcc_server_t *srv, char const *interface) /* {{{ */ /* else: Not a multicast interface. */ #if defined(SO_BINDTODEVICE) - status = setsockopt(srv->fd, SOL_SOCKET, SO_BINDTODEVICE, interface, - (socklen_t)(strlen(interface) + 1)); + status = setsockopt(srv->fd, SOL_SOCKET, SO_BINDTODEVICE, iface, + (socklen_t)(strlen(iface) + 1)); if (status != 0) return -1; #endif diff --git a/src/libcollectdclient/network_buffer.c b/src/libcollectdclient/network_buffer.c index 5a1ee8d0..44d93e07 100644 --- a/src/libcollectdclient/network_buffer.c +++ b/src/libcollectdclient/network_buffer.c @@ -24,6 +24,10 @@ * Florian octo Forster **/ +#ifdef WIN32 +#include "gnulib_config.h" +#endif + #include "config.h" #include /* htons */ diff --git a/src/libcollectdclient/server.c b/src/libcollectdclient/server.c index 1095ebaf..26876162 100644 --- a/src/libcollectdclient/server.c +++ b/src/libcollectdclient/server.c @@ -23,6 +23,10 @@ * Florian octo Forster **/ +#ifdef WIN32 +#include "gnulib_config.h" +#endif + #include "config.h" #if !defined(__GNUC__) || !__GNUC__ @@ -48,6 +52,11 @@ #include #define DEBUG(...) printf(__VA_ARGS__) +#ifdef WIN32 +#include +#define AI_ADDRCONFIG 0 +#endif + static bool is_multicast(struct addrinfo const *ai) { if (ai->ai_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)ai->ai_addr; @@ -81,13 +90,20 @@ static int server_multicast_join(lcc_listener_t *srv, struct ip_mreqn mreq = { .imr_address.s_addr = INADDR_ANY, .imr_multiaddr.s_addr = sa->sin_addr.s_addr, - .imr_ifindex = if_nametoindex(srv->interface), + .imr_ifindex = if_nametoindex(srv->iface), }; #else +#ifdef WIN32 struct ip_mreq mreq = { + .imr_interface.s_addr = INADDR_ANY, .imr_multiaddr.s_addr = sa->sin_addr.s_addr, }; -#endif +#else + struct ip_mreq mreq = { + .imr_address.s_addr = INADDR_ANY, .imr_multiaddr.s_addr = sa->s_addr, + }; +#endif /* WIN32 */ +#endif /* HAVE_STRUCT_IP_MREQN_IMR_IFINDEX */ status = setsockopt(srv->conn, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if (status == -1) @@ -106,7 +122,7 @@ static int server_multicast_join(lcc_listener_t *srv, return errno; struct ipv6_mreq mreq6 = { - .ipv6mr_interface = if_nametoindex(srv->interface), + .ipv6mr_interface = if_nametoindex(srv->iface), }; memmove(&mreq6.ipv6mr_multiaddr, &sa->sin6_addr, sizeof(struct in6_addr)); diff --git a/src/liboconfig/scanner.l b/src/liboconfig/scanner.l index cfd9a5c9..7efa78a3 100644 --- a/src/liboconfig/scanner.l +++ b/src/liboconfig/scanner.l @@ -27,6 +27,11 @@ */ %{ +#ifdef WIN32 +#include "gnulib_config.h" +#include "config.h" +#endif + #include #include #include "oconfig.h"