diff --git a/src/Makefile.am b/src/Makefile.am index 3229c5de..82f4f40b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,6 +6,7 @@ bin_PROGRAMS = icecast noinst_HEADERS = \ icecasttypes.h \ + version.h \ admin.h \ resourcematch.h \ main.h \ @@ -63,6 +64,7 @@ noinst_HEADERS = \ icecast_SOURCES = \ main.c \ + version.c \ cfgfile.c \ logging.c \ sighandler.c \ diff --git a/src/admin.c b/src/admin.c index 422fa0ad..ab0cd160 100644 --- a/src/admin.c +++ b/src/admin.c @@ -37,25 +37,6 @@ #include #endif -#ifdef HAVE_OPENSSL -#include -#endif - -#include - -#ifdef HAVE_THEORA -#include -#endif - -#ifdef HAVE_SPEEX -#include -#endif - -#ifdef HAVE_CURL -#include -#include -#endif - #ifdef HAVE_UNAME #include #endif @@ -65,6 +46,7 @@ #include "common/net/sock.h" #include "admin.h" +#include "version.h" #include "compat.h" #include "cfgfile.h" #include "connection.h" @@ -1857,24 +1839,6 @@ static void command_dashboard (client_t *client, source_t *source, adm refobject_unref(report); } -#ifdef HAVE_SPEEX -static inline const char *get_speex_version(void) -{ - const char *version; - if (speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, &version) != 0) - return NULL; - return version; -} -#endif - -static inline const char *get_igloo_version(void) -{ - const char *version; - if (igloo_version_get(&version, NULL, NULL, NULL) != igloo_ERROR_NONE) - return NULL; - return version; -} - static void command_version (client_t *client, source_t *source, admin_format_t response) { reportxml_t *report = client_get_reportxml("8cdfc150-094d-42f7-9c61-f9fb9a6e07e7", NULL, NULL); @@ -1886,61 +1850,8 @@ static void command_version (client_t *client, source_t *source, adm reportxml_node_t *cflags = reportxml_node_new(REPORTXML_NODE_TYPE_VALUE, NULL, NULL, NULL); reportxml_node_t *rflags = reportxml_node_new(REPORTXML_NODE_TYPE_VALUE, NULL, NULL, NULL); ice_config_t *icecast_config; -#ifdef HAVE_CURL - const curl_version_info_data * curl_runtime_version = curl_version_info(CURLVERSION_NOW); -#endif - struct { - const char *name; - const char *compiletime; - const char *runtime; - } dependency_versions[] = { - {"libigloo", NULL, get_igloo_version()}, - {"libxml2", LIBXML_DOTTED_VERSION, NULL}, -#if defined(HAVE_OPENSSL) && defined(OPENSSL_VERSION_TEXT) - {"OpenSSL", OPENSSL_VERSION_TEXT, NULL}, -#endif - {"libvorbis", NULL, vorbis_version_string()}, -#ifdef HAVE_THEORA - {"libtheora", NULL, theora_version_string()}, -#endif -#ifdef HAVE_SPEEX - {"libspeex", NULL, get_speex_version()}, -#endif -#ifdef HAVE_CURL - {"libcurl", LIBCURL_VERSION, curl_runtime_version->version}, -#endif - {NULL, NULL, NULL} - }; - const char *compiletime_flags[] = { -#ifdef HAVE_POLL - "poll", -#endif -#ifdef HAVE_SYS_SELECT_H - "select", -#endif -#ifdef HAVE_UNAME - "uname", -#endif -#ifdef HAVE_GETHOSTNAME - "gethostname", -#endif -#ifdef HAVE_GETADDRINFO - "getaddrinfo", -#endif -#ifdef HAVE_CRYPT - "crypt", -#endif -#ifdef HAVE_CRYPT_R - "crypt_r", -#endif -#ifdef WIN32 - "win32", -#endif -#ifdef DEVEL_LOGGING - "developer-logging", -#endif - NULL, - }; + const char * const * compiletime_flags = version_get_compiletime_flags(); + const icecast_dependency_t * dependency_versions = version_get_dependencies(); size_t i; reportxml_node_set_attribute(resource, "type", "result"); diff --git a/src/main.c b/src/main.c index 3ce3eb22..6e72d6a9 100644 --- a/src/main.c +++ b/src/main.c @@ -65,6 +65,7 @@ #include #include "main.h" +#include "version.h" #include "cfgfile.h" #include "util.h" #include "sighandler.h" @@ -222,6 +223,38 @@ void main_config_reload(ice_config_t *config) pidfile_update(config, 0); } +static void show_version(bool full) +{ + printf("%s\n", ICECAST_VERSION_STRING); + + if (full) { + const char * const * compiletime_flag = version_get_compiletime_flags(); + const icecast_dependency_t * dependencies = version_get_dependencies(); + size_t i; + + printf("\n"); + + printf("Address bits: %u\n", (unsigned int)sizeof(void*)*8); +#ifdef HAVE_SYS_SELECT_H + printf("fd set size: %u\n", (unsigned int)FD_SETSIZE); +#endif + + printf("Compile time flags: "); + for (i = 0; compiletime_flag[i]; i++) + printf("%s ", compiletime_flag[i]); + printf("\n"); + + printf("Dependencies:\n"); + for (i = 0; dependencies[i].name; i++) { + printf(" %s:\n", dependencies[i].name); + if (dependencies[i].compiletime) + printf(" compile time: %s\n", dependencies[i].compiletime); + if (dependencies[i].runtime) + printf(" run time: %s\n", dependencies[i].runtime); + } + } +} + static bool _parse_config_opts(int argc, char **argv, char *filename, size_t size) { int i; @@ -258,7 +291,10 @@ static bool _parse_config_opts(int argc, char **argv, char *filename, size_t siz background = true; #endif } else if (strcmp(opt, "-v") == 0 || strcmp(opt, "--version") == 0) { - fprintf(stdout, "%s\n", ICECAST_VERSION_STRING); + show_version(false); + exit(0); + } else if (strcmp(opt, "-V") == 0) { + show_version(true); exit(0); } else if (strcmp(opt, "-c") == 0) { if ((i + 1) < argc) { diff --git a/src/version.c b/src/version.c new file mode 100644 index 00000000..d2074ceb --- /dev/null +++ b/src/version.c @@ -0,0 +1,155 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2023-2023, Philipp "ph3-der-loewe" Schafft , + */ + +/** + * Client authentication functions + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#ifdef HAVE_PTHREAD +#include +#else +#error "No pthread support" +#endif + +#include + +#ifdef HAVE_OPENSSL +#include +#endif + +#include + +#ifdef HAVE_THEORA +#include +#endif + +#ifdef HAVE_SPEEX +#include +#endif + +#ifdef HAVE_CURL +#include +#include +#endif + +#include "version.h" + +#include "logging.h" +#define CATMODULE "version" + +const char * const * version_get_compiletime_flags(void) +{ + static const char * const compiletime_flags[] = { +#ifdef HAVE_POLL + "poll", +#endif +#ifdef HAVE_SYS_SELECT_H + "select", +#endif +#ifdef HAVE_UNAME + "uname", +#endif +#ifdef HAVE_GETHOSTNAME + "gethostname", +#endif +#ifdef HAVE_GETADDRINFO + "getaddrinfo", +#endif +#ifdef HAVE_CRYPT + "crypt", +#endif +#ifdef HAVE_CRYPT_R + "crypt_r", +#endif +#ifdef WIN32 + "win32", +#endif +#ifdef DEVEL_LOGGING + "developer-logging", +#endif + NULL, + }; + + return compiletime_flags; +} + +#ifdef HAVE_SPEEX +static inline const char *get_speex_version(void) +{ + const char *version; + if (speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, &version) != 0) + return NULL; + return version; +} +#endif + +static inline const char *get_igloo_version(void) +{ + const char *version; + if (igloo_version_get(&version, NULL, NULL, NULL) != igloo_ERROR_NONE) + return NULL; + return version; +} + + +#ifdef HAVE_PTHREAD +static pthread_once_t version_detect = PTHREAD_ONCE_INIT; +static icecast_dependency_t dependency_versions_real[32]; + +static inline void dependency_versions_add(size_t i, const char *name, const char *compiletime, const char *runtime) +{ + if (i >= ((sizeof(dependency_versions_real)/sizeof(*dependency_versions_real)) - 1)) /* substract 1 for final NULL-row */ + return; + + dependency_versions_real[i].name = name; + dependency_versions_real[i].compiletime = compiletime; + dependency_versions_real[i].runtime = runtime; +} + +static void version_init(void) +{ +#ifdef HAVE_CURL + const curl_version_info_data * curl_runtime_version = curl_version_info(CURLVERSION_NOW); +#endif + size_t i = 0; + + dependency_versions_add(i++, "libigloo", NULL, get_igloo_version()); + dependency_versions_add(i++, "libxml2", LIBXML_DOTTED_VERSION, NULL); +#if defined(HAVE_OPENSSL) && defined(OPENSSL_VERSION_TEXT) + dependency_versions_add(i++, "OpenSSL", OPENSSL_VERSION_TEXT, NULL); +#endif + dependency_versions_add(i++, "libvorbis", NULL, vorbis_version_string()); +#ifdef HAVE_THEORA + dependency_versions_add(i++, "libtheora", NULL, theora_version_string()); +#endif +#ifdef HAVE_SPEEX + dependency_versions_add(i++, "libspeex", NULL, get_speex_version()); +#endif +#ifdef HAVE_CURL + dependency_versions_add(i++, "libcurl", LIBCURL_VERSION, curl_runtime_version->version); +#endif +} +#endif + + +const icecast_dependency_t * version_get_dependencies(void) +{ +#ifdef HAVE_PTHREAD + if (pthread_once(&version_detect, version_init) != 0) + return NULL; +#endif + + return dependency_versions_real; +} diff --git a/src/version.h b/src/version.h new file mode 100644 index 00000000..ab8e4729 --- /dev/null +++ b/src/version.h @@ -0,0 +1,24 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2023-2023, Philipp "ph3-der-loewe" Schafft , + */ + +#ifndef __VERSION_H__ +#define __VERSION_H__ + +#include "icecasttypes.h" + +typedef struct { + const char *name; + const char *compiletime; + const char *runtime; +} icecast_dependency_t; + +const char * const * version_get_compiletime_flags(void); + +const icecast_dependency_t * version_get_dependencies(void); + +#endif /* __VERSION_H__ */