Mercurial > irccd
changeset 948:21a91311c8ea
cmake: switch back, GNU make is painful
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,54 @@ +# +# CMakeLists.txt -- CMake build for irccd +# +# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +cmake_minimum_required(VERSION 3.12) +project(irccd) + +set_property(GLOBAL PROPERTY USE_FOLDERS On) + +set(IRCCD_VERSION_MAJOR 4) +set(IRCCD_VERSION_MINOR 0) +set(IRCCD_VERSION_PATCH 0) + +option(IRCCD_WITH_JS "Enable Javascript" On) +option(IRCCD_WITH_SSL "Enable SSL support" On) +option(IRCCD_WITH_IRCCD "Enable irccd daemon" On) +option(IRCCD_WITH_IRCCDCTL "Enable irccdctl utility" On) +option(IRCCD_WITH_TESTS "Enable unit tests" Off) + +if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + set(CMAKE_C_FLAGS "-Wall -Wextra") +endif () + +include(GNUInstallDirs) + +add_subdirectory(extern/libcompat) + +if (IRCCD_WITH_JS) + add_subdirectory(extern/libduktape) +endif () + +add_subdirectory(lib) +add_subdirectory(irccd) +add_subdirectory(irccdctl) + +if (IRCCD_WITH_TESTS) + enable_testing() + add_subdirectory(extern/libgreatest) + add_subdirectory(tests) +endif ()
--- a/Makefile Sat Jan 16 09:45:33 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,172 +0,0 @@ -# -# Makefile -- POSIX makefile for irccd -# -# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -.SUFFIXES: -.SUFFIXES: .o .c - -include config.mk - -MAJOR= 4 -MINOR= 0 -PATCH= 0 - -IRCCD= irccd/irccd -IRCCD_SRCS= irccd/main.c -IRCCD_OBJS= ${IRCCD_SRCS:.c=.o} -IRCCD_DEPS= ${IRCCD_SRCS:.c=.d} - -IRCCDCTL= irccdctl/irccdctl -IRCCDCTL_SRCS= irccdctl/main.c -IRCCDCTL_OBJS= ${IRCCDCTL_SRCS:.c=.o} -IRCCDCTL_DEPS= ${IRCCDCTL_SRCS:.c=.d} - -LIBCOMPAT= extern/libcompat/libirccd-compat.a - -ifeq (${WITH_JS},yes) -LIBDUKTAPE= extern/libduktape/libirccd-duktape.a -endif - -LIBIRCCD= lib/libirccd.a -LIBIRCCD_SRCS= lib/irccd/channel.c -LIBIRCCD_SRCS+= lib/irccd/dl-plugin.c -LIBIRCCD_SRCS+= lib/irccd/irccd.c -LIBIRCCD_SRCS+= lib/irccd/log.c -LIBIRCCD_SRCS+= lib/irccd/peer.c -LIBIRCCD_SRCS+= lib/irccd/plugin.c -LIBIRCCD_SRCS+= lib/irccd/rule.c -LIBIRCCD_SRCS+= lib/irccd/server.c -LIBIRCCD_SRCS+= lib/irccd/subst.c -LIBIRCCD_SRCS+= lib/irccd/transport.c -LIBIRCCD_SRCS+= lib/irccd/util.c - -ifeq (${WITH_JS},yes) -LIBIRCCD_SRCS+= lib/irccd/js-plugin.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-chrono.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-file.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-irccd.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-logger.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-plugin.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-server.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-system.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-timer.c -LIBIRCCD_SRCS+= lib/irccd/jsapi-unicode.c -LIBIRCCD_SRCS+= lib/irccd/unicode.c -endif - -LIBIRCCD_OBJS= ${LIBIRCCD_SRCS:.c=.o} -LIBIRCCD_DEPS= ${LIBIRCCD_SRCS:.c=.d} - -TESTS= tests/test-channel.c -TESTS+= tests/test-dl-plugin.c -TESTS+= tests/test-log.c -TESTS+= tests/test-rule.c -TESTS+= tests/test-subst.c -TESTS+= tests/test-util.c -TESTS_OBJS= ${TESTS:.c=} - -DEFINES= -D_BSD_SOURCE -DEFINES+= -DSOURCEDIR=\"`pwd`\" - -INCS= -I extern/libcompat/include -ifeq (${WITH_JS},yes) -INCS+= -I extern/libduktape -endif -INCS+= -I extern/libgreatest -INCS+= -I lib - -LIBS= -L extern/libcompat -ifeq (${WITH_JS},yes) -LIBS+= -L extern/libduktape -endif -LIBS+= -L lib - -LIBS+= -l irccd-compat -ifeq (${WITH_JS},yes) -LIBS+= -l irccd-duktape -endif -LIBS+= -l irccd - -ifeq (${WITH_SSL},yes) -LIBS+= -l ssl -l crypto -endif - -all: ${IRCCD} ${IRCCDCTL} - -.c.o: - ${CMD.cc} - --include ${LIBIRCCD_DEPS} --include ${IRCCD_DEPS} - -${LIBCOMPAT}: - ${MAKE} CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" -C extern/libcompat - -ifeq (${WITH_JS},yes) -${LIBDUKTAPE}: - ${MAKE} CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" -C extern/libduktape -endif - -ifneq (${WITH_JS},yes) -EXTRA_SEDS+= -e "/IRCCD_WITH_JS/d" -endif - -ifneq (${WITH_SSL},yes) -EXTRA_SEDS+= -e "/IRCCD_WITH_SSL/d" -endif - -lib/irccd/config.h: lib/irccd/config.h.in Makefile config.mk - sed -e "s/@IRCCD_VERSION_MAJOR@/${MAJOR}/" \ - -e "s/@IRCCD_VERSION_MINOR@/${MINOR}/" \ - -e "s/@IRCCD_VERSION_PATCH@/${PATCH}/" \ - ${EXTRA_SEDS} < $< > $@ - -${LIBIRCCD_OBJS}: ${LIBCOMPAT} lib/irccd/config.h - -${LIBIRCCD}: ${LIBIRCCD_OBJS} ${LIBDUKTAPE} - ${CMD.ar} - -${IRCCD}: ${IRCCD_OBJS} ${LIBCOMPAT} ${LIBDUKTAPE} ${LIBIRCCD} - ${CMD.ccld} - -${IRCCDCTL}: ${IRCCDCTL_OBJS} - ${CMD.ccld} - -# Unit tests. -tests/test-%: tests/test-%.c - ${CC} ${DEFINES} ${INCS} ${CFLAGS} -o $@ $< ${LIBS} ${LDFLAGS} - -${TESTS_OBJS}: ${LIBIRCCD} - -# Sample plugin for test-dl-plugin. -tests/example-dl-plugin${EXT.shared}: tests/example-dl-plugin.o - ${CMD.ld-shared} - -tests/test-dl-plugin: tests/example-dl-plugin${EXT.shared} - -tests: ${TESTS_OBJS} - for t in ${TESTS_OBJS}; do ./$$t; done - -clean: - ${MAKE} -C extern/libcompat clean - ${MAKE} -C extern/libduktape clean - rm -f ${LIBIRCCD} ${LIBIRCCD_OBJS} ${LIBIRCCD_DEPS} - rm -f ${IRCCD} ${IRCCD_OBJS} ${IRCCD_DEPS} - rm -f tests/example-dl-plugin${EXT.shared} tests/example-dl-plugin.o tests/example-dl-plugin.d - rm -f ${TESTS_OBJS} - -.PHONY: all clean tests
--- a/config.mk Sat Jan 16 09:45:33 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -# -# config.mk -- POSIX makefile for irccd -# -# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -# Build tools. -CC= cc -AR= ar - -CFLAGS= -g -O0 -fsanitize=address,undefined -LDFLAGS= -fsanitize=address,undefined - -# Installation paths. -PREFIX= /usr/local -BINDIR= bin - -# User options. -WITH_JS= yes -WITH_SSL= no - -# System dependant macros. -OS:= $(shell uname -s) - -# Standard commands. -CMD.cc= ${CC} ${DEFINES} ${INCS} ${CFLAGS} -MMD -c $< -o $@ -CMD.ccld= ${CC} ${DEFINES} ${INCS} ${CFLAGS} -o $@ $< ${LIBS} ${LDFLAGS} -CMD.ar= ${AR} -rc $@ $^ - -# Determine shared library extension and command to generate. -ifeq (Darwin,${OS}) -EXT.shared= .dylib -CMD.ld-shared= ${CC} -dynamiclib -o $@ $^ ${LDFLAGS} -else -EXT.shared= .so -CMD.ld-shared= ${CC} -shared -o $@ $^ ${LDFLAGS} -endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,170 @@ +# +# CMakeLists.txt -- CMake build system for libcompat +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +cmake_minimum_required(VERSION 3.10) +project(libirccd-compat) + +option(COMPAT_WITH_TESTS "Enable tests" Off) + +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckStructHasMember) + +set( + SOURCES + ${libirccd-compat_SOURCE_DIR}/src/compat.c + ${libirccd-compat_SOURCE_DIR}/src/compat.h.in +) + +set( + FUNCTIONS + # BSD extensions. + err + errc + errx + pledge + reallocarray + recallocarray + strlcat + strlcpy + strsep + verr + verrc + verrx + vsyslog + vwarn + vwarnc + vwarnx + warn + warnc + warnx + # POSIX functions. + basename + dirname + getopt + strdup + strndup + strnlen +) + +set( + INCLUDES + # BSD extensions. + err.h + # POSIX extensions. + unistd.h + libgen.h +) + +foreach (f ${FUNCTIONS}) + string(TOUPPER ${f} var) + + check_function_exists(${f} COMPAT_HAVE_${var}) + + if (NOT COMPAT_HAVE_${var}) + list(APPEND SOURCES ${libirccd-compat_SOURCE_DIR}/src/${f}.c) + endif () +endforeach () + +# Functionalities we can't replace +check_include_file(syslog.h COMPAT_HAVE_SYSLOG_H) + +add_library(libirccd-compat STATIC ${SOURCES}) +target_include_directories( + libirccd-compat + PUBLIC + $<BUILD_INTERFACE:${libirccd-compat_BINARY_DIR}> +) +set_target_properties(libirccd-compat PROPERTIES PREFIX "") + +# Remove useless C4996 warning about "deprecated" functions from MSVC. +if (CMAKE_C_COMPILER_ID MATCHES MSVC) + target_compile_options(libirccd-compat PUBLIC /wd4996) +endif () + +foreach (i ${INCLUDES}) + string(TOUPPER ${i} var) + string(REGEX REPLACE "\\." "_" var ${var}) + + check_include_file(${i} COMPAT_HAVE_${var}) + + if (NOT COMPAT_HAVE_${var}) + file(WRITE ${libirccd-compat_BINARY_DIR}/${i} "/* Empty stub for ${i}. */\n") + endif () +endforeach () + +# POSIX dirent.h +check_include_file(dirent.h COMPAT_HAVE_DIRENT_H) + +if (NOT COMPAT_HAVE_DIRENT_H) + if (CMAKE_SYSTEM_NAME MATCHES "Windows") + target_include_directories( + libirccd-compat + PUBLIC + $<BUILD_INTERFACE:${libirccd-compat_SOURCE_DIR}/win/dirent> + ) + endif () +endif () + +# Math library +find_library(COMPAT_HAVE_LIBM m) + +if (NOT COMPAT_HAVE_LIBM) + add_library(m INTERFACE) +endif () + +# POSIX dlfcn.h +check_include_file(dlfcn.h COMPAT_HAVE_DLFCN_H) + +if (NOT COMPAT_HAVE_DLFCN_H) + if (CMAKE_SYSTEM_NAME MATCHES "Windows") + add_subdirectory(win/dlfcn) + endif () +else () + # Some systems may not provide the dl library. + find_library(COMPAT_HAVE_LIBDL dl) + + if (NOT COMPAT_HAVE_LIBDL) + add_library(dl INTERFACE) + endif () +endif () + +# struct stat fields +check_struct_has_member("struct stat" st_atime sys/stat.h COMPAT_HAVE_STAT_ST_ATIME) +check_struct_has_member("struct stat" st_blksize sys/stat.h COMPAT_HAVE_STAT_ST_BLKSIZE) +check_struct_has_member("struct stat" st_blocks sys/stat.h COMPAT_HAVE_STAT_ST_BLOCKS) +check_struct_has_member("struct stat" st_ctime sys/stat.h COMPAT_HAVE_STAT_ST_CTIME) +check_struct_has_member("struct stat" st_dev sys/stat.h COMPAT_HAVE_STAT_ST_DEV) +check_struct_has_member("struct stat" st_gid sys/stat.h COMPAT_HAVE_STAT_ST_GID) +check_struct_has_member("struct stat" st_ino sys/stat.h COMPAT_HAVE_STAT_ST_INO) +check_struct_has_member("struct stat" st_mode sys/stat.h COMPAT_HAVE_STAT_ST_MODE) +check_struct_has_member("struct stat" st_mtime sys/stat.h COMPAT_HAVE_STAT_ST_MTIME) +check_struct_has_member("struct stat" st_nlink sys/stat.h COMPAT_HAVE_STAT_ST_NLINK) +check_struct_has_member("struct stat" st_rdev sys/stat.h COMPAT_HAVE_STAT_ST_RDEV) +check_struct_has_member("struct stat" st_size sys/stat.h COMPAT_HAVE_STAT_ST_SIZE) +check_struct_has_member("struct stat" st_uid sys/stat.h COMPAT_HAVE_STAT_ST_UID) + +if (COMPAT_WITH_TESTS) + enable_testing() + add_subdirectory(tests) +endif () + +configure_file( + ${libirccd-compat_SOURCE_DIR}/src/compat.h.in + ${libirccd-compat_BINARY_DIR}/compat.h +)
--- a/extern/libcompat/Makefile Sat Jan 16 09:45:33 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -# -# Makefile -- POSIX make for libcompat -# -# Copyright (c) 2020 David Demelier <markand@malikania.fr> -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -.POSIX: - -.SUFFIXES: -.SUFFIXES: .c .o .h .sh - -FUNCTIONS_SRCS= src/basename.c \ - src/dirname.c \ - src/err.c \ - src/errc.c \ - src/errx.c \ - src/getopt.c \ - src/pledge.c \ - src/reallocarray.c \ - src/recallocarray.c \ - src/strdup.c \ - src/strlcat.c \ - src/strlcpy.c \ - src/strndup.c \ - src/strnlen.c \ - src/strsep.c \ - src/verr.c \ - src/verrc.c \ - src/verrx.c \ - src/vwarn.c \ - src/vwarnc.c \ - src/vwarnx.c \ - src/warn.c \ - src/warnc.c \ - src/warnx.c - -INCLUDES_SRCS= include/err.h \ - include/libgen.h \ - include/unistd.h - -LIBS_SRCS= lib/libm.a \ - lib/libdl.a \ - lib/libintl.a - -FUNCTIONS_OBJS= ${FUNCTIONS_SRCS:.c=.o} -FUNCTIONS_HDRS= ${FUNCTIONS_SRCS:.c=.h} - -LIB= libirccd-compat.a - -all: ${LIB} - -.sh: - @cp $< $@ - @chmod +x $@ - -.c.o: - @CC="${CC}" CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" ./trycompile -c ${*F} - -.c.h: - CC="${CC}" CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" ./trycompile ${*F} - -${FUNCTIONS_HDRS} ${FUNCTIONS_OBJS}: trycompile - -include: Makefile tryinclude - @for h in ${INCLUDES_SRCS}; do CC="${CC}" CFLAGS="${CFLAGS}" ./tryinclude `basename $$h`; done - @touch include - -lib: Makefile trylib - @for l in ${LIBS_SRCS}; do AR="${AR}" CC="${CC}" CFLAGS="${CFLAGS}" ./trylib `basename $$l`; done - @touch lib - -${LIB}: include lib ${FUNCTIONS_HDRS} ${FUNCTIONS_OBJS} - @mkdir -p ${@D} - @${AR} -rc $@ ${FUNCTIONS_OBJS} >/dev/null 2>&1 - -clean: - @rm -f trycompile tryinclude trylib - @rm -f ${LIB} - @rm -f ${FUNCTIONS_OBJS} - @rm -f ${FUNCTIONS_HDRS} - @rm -f ${INCLUDES_SRCS} - -.PHONY: all clean
--- a/extern/libcompat/include/compat.h Sat Jan 16 09:45:33 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -#ifndef LIBCOMPAT_COMPAT_H -#define LIBCOMPAT_COMPAT_H - -#include "../src/basename.h" -#include "../src/dirname.h" -#include "../src/err.h" -#include "../src/errc.h" -#include "../src/errx.h" -#include "../src/getopt.h" -#include "../src/pledge.h" -#include "../src/reallocarray.h" -#include "../src/recallocarray.h" -#include "../src/strdup.h" -#include "../src/strlcat.h" -#include "../src/strlcpy.h" -#include "../src/strndup.h" -#include "../src/strnlen.h" -#include "../src/strsep.h" -#include "../src/verr.h" -#include "../src/verrc.h" -#include "../src/verrx.h" -#include "../src/vwarn.h" -#include "../src/vwarnc.h" -#include "../src/vwarnx.h" -#include "../src/warn.h" -#include "../src/warnc.h" -#include "../src/warnx.h" - -#include <stdarg.h> -#include <stddef.h> - -#ifndef COMPAT_HAVE_BASENAME -char * -basename(char *); -#endif - -#ifndef COMPAT_HAVE_DIRNAME -char * -dirname(char *); -#endif - -#ifndef COMPAT_HAVE_ERR -void -err(int, const char *, ...); -#endif - -#ifndef COMPAT_HAVE_ERRC -void -errc(int, int, const char *, ...); -#endif - -#ifndef COMPAT_HAVE_ERRX -void -errx(int, const char *, ...); -#endif - -#ifndef COMPAT_HAVE_VERR -void -verr(int, const char *, va_list); -#endif - -#ifndef COMPAT_HAVE_VERRC -void -verrc(int, int, const char *, va_list); -#endif - -#ifndef COMPAT_HAVE_VERRX -void -verrx(int, const char *, va_list); -#endif - -#ifndef COMPAT_HAVE_VWARN -void -vwarn(const char *, va_list); -#endif - -#ifndef COMPAT_HAVE_VWARNC -void -vwarnc(int, const char *, va_list); -#endif - -#ifndef COMPAT_HAVE_VWARNX -void -vwarnx(const char *, va_list); -#endif - -#ifndef COMPAT_HAVE_WARN -void -warn(const char *, ...); -#endif - -#ifndef COMPAT_HAVE_WARNC -void -warnc(int, const char *, ...); -#endif - -#ifndef COMPAT_HAVE_WARNX -void -warnx(const char *, ...); -#endif - -#ifndef COMPAT_HAVE_GETOPT -extern int opterr; -extern int optind; -extern int optopt; -extern int optreset; -extern char *optarg; - -int -getopt(int, char **, const char *); -#endif - -#ifndef COMPAT_HAVE_PLEDGE -int -pledge(const char *, const char *); -#endif - -#ifndef COMPAT_HAVE_REALLOCARRAY -void * -reallocarray(void *, size_t, size_t); -#endif - -#ifndef COMPAT_HAVE_RECALLOCARRAY -void * -recallocarray(void *, size_t, size_t, size_t); -#endif - -#ifndef COMPAT_HAVE_STRDUP -char * -strdup(const char *); -#endif - -#ifndef COMPAT_HAVE_STRLCAT -size_t -strlcat(char *, const char *, size_t); -#endif - -#ifndef COMPAT_HAVE_STRLCPY -size_t -strlcpy(char *, const char *, size_t); -#endif - -#ifndef COMPAT_HAVE_STRNDUP -char * -strndup(const char *, size_t); -#endif - -#ifndef COMPAT_HAVE_STRNLEN -size_t -strnlen(const char *, size_t); -#endif - -#ifndef COMPAT_HAVE_STRSEP -char * -strsep(char **, const char *); -#endif - -#endif /* !LIBCOMPAT_COMPAT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/src/compat.h.in Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,172 @@ +#ifndef LIBCOMPAT_COMPAT_H +#define LIBCOMPAT_COMPAT_H + +#cmakedefine COMPAT_HAVE_BASENAME +#cmakedefine COMPAT_HAVE_DIRNAME +#cmakedefine COMPAT_HAVE_ERR +#cmakedefine COMPAT_HAVE_ERRC +#cmakedefine COMPAT_HAVE_ERRX +#cmakedefine COMPAT_HAVE_GETOPT +#cmakedefine COMPAT_HAVE_PLEDGE +#cmakedefine COMPAT_HAVE_REALLOCARRAY +#cmakedefine COMPAT_HAVE_RECALLOCARRAY +#cmakedefine COMPAT_HAVE_STRDUP +#cmakedefine COMPAT_HAVE_STRLCAT +#cmakedefine COMPAT_HAVE_STRLCPY +#cmakedefine COMPAT_HAVE_STRNDUP +#cmakedefine COMPAT_HAVE_STRNLEN +#cmakedefine COMPAT_HAVE_STRSEP +#cmakedefine COMPAT_HAVE_VERR +#cmakedefine COMPAT_HAVE_VERRC +#cmakedefine COMPAT_HAVE_VERRX +#cmakedefine COMPAT_HAVE_VWARN +#cmakedefine COMPAT_HAVE_VWARNC +#cmakedefine COMPAT_HAVE_VWARNX +#cmakedefine COMPAT_HAVE_WARN +#cmakedefine COMPAT_HAVE_WARNC +#cmakedefine COMPAT_HAVE_WARNX + +#cmakedefine COMPAT_HAVE_STAT_ST_ATIME +#cmakedefine COMPAT_HAVE_STAT_ST_BLKSIZE +#cmakedefine COMPAT_HAVE_STAT_ST_BLOCKS +#cmakedefine COMPAT_HAVE_STAT_ST_CTIME +#cmakedefine COMPAT_HAVE_STAT_ST_DEV +#cmakedefine COMPAT_HAVE_STAT_ST_GID +#cmakedefine COMPAT_HAVE_STAT_ST_INO +#cmakedefine COMPAT_HAVE_STAT_ST_MODE +#cmakedefine COMPAT_HAVE_STAT_ST_MTIME +#cmakedefine COMPAT_HAVE_STAT_ST_NLINK +#cmakedefine COMPAT_HAVE_STAT_ST_RDEV +#cmakedefine COMPAT_HAVE_STAT_ST_SIZE +#cmakedefine COMPAT_HAVE_STAT_ST_UID + +#include <stdarg.h> +#include <stddef.h> + +#ifndef COMPAT_HAVE_BASENAME +char * +basename(char *); +#endif + +#ifndef COMPAT_HAVE_DIRNAME +char * +dirname(char *); +#endif + +#ifndef COMPAT_HAVE_ERR +void +err(int, const char *, ...); +#endif + +#ifndef COMPAT_HAVE_ERRC +void +errc(int, int, const char *, ...); +#endif + +#ifndef COMPAT_HAVE_ERRX +void +errx(int, const char *, ...); +#endif + +#ifndef COMPAT_HAVE_VERR +void +verr(int, const char *, va_list); +#endif + +#ifndef COMPAT_HAVE_VERRC +void +verrc(int, int, const char *, va_list); +#endif + +#ifndef COMPAT_HAVE_VERRX +void +verrx(int, const char *, va_list); +#endif + +#ifndef COMPAT_HAVE_VWARN +void +vwarn(const char *, va_list); +#endif + +#ifndef COMPAT_HAVE_VWARNC +void +vwarnc(int, const char *, va_list); +#endif + +#ifndef COMPAT_HAVE_VWARNX +void +vwarnx(const char *, va_list); +#endif + +#ifndef COMPAT_HAVE_WARN +void +warn(const char *, ...); +#endif + +#ifndef COMPAT_HAVE_WARNC +void +warnc(int, const char *, ...); +#endif + +#ifndef COMPAT_HAVE_WARNX +void +warnx(const char *, ...); +#endif + +#ifndef COMPAT_HAVE_GETOPT +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; +extern char *optarg; + +int +getopt(int, char **, const char *); +#endif + +#ifndef COMPAT_HAVE_PLEDGE +int +pledge(const char *, const char *); +#endif + +#ifndef COMPAT_HAVE_REALLOCARRAY +void * +reallocarray(void *, size_t, size_t); +#endif + +#ifndef COMPAT_HAVE_RECALLOCARRAY +void * +recallocarray(void *, size_t, size_t, size_t); +#endif + +#ifndef COMPAT_HAVE_STRDUP +char * +strdup(const char *); +#endif + +#ifndef COMPAT_HAVE_STRLCAT +size_t +strlcat(char *, const char *, size_t); +#endif + +#ifndef COMPAT_HAVE_STRLCPY +size_t +strlcpy(char *, const char *, size_t); +#endif + +#ifndef COMPAT_HAVE_STRNDUP +char * +strndup(const char *, size_t); +#endif + +#ifndef COMPAT_HAVE_STRNLEN +size_t +strnlen(const char *, size_t); +#endif + +#ifndef COMPAT_HAVE_STRSEP +char * +strsep(char **, const char *); +#endif + +#endif /* !LIBCOMPAT_COMPAT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/src/vsyslog.c Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,39 @@ +/* + * vsyslog.c -- fallback implementation + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "compat.h" + +#if defined(COMPAT_HAVE_SYSLOG_H) + +#include <assert.h> +#include <stdarg.h> +#include <stdio.h> +#include <syslog.h> + +void +vsyslog(int priority, const char *msg, va_list ap) +{ + assert(msg); + + char buf[1024] = {0}; + + if (vsnprintf(buf, sizeof (buf), fmt, ap) >= 0) + syslog(priority, "%s", buf); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/tests/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,38 @@ +# +# CMakeLists.txt -- CMake build system for libcompat +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(tests) + +function(define_test name) + add_executable(test-${name} test-${name}.c) + add_test(NAME test-${name} COMMAND test-${name}) + target_link_libraries(test-${name} libcompat) +endfunction() + +# POSIX dlfcn/dlopen/dlsym. +define_test(dlfcn) +set_target_properties(test-dlfcn PROPERTIES ENABLE_EXPORTS On) +target_link_libraries(test-dlfcn dl) + +# POSIX opendir/readdir. +define_test(dirent) +target_compile_definitions(test-dirent PRIVATE DIRECTORY="${tests_SOURCE_DIR}") + +# BSD and POSIX functions. +define_test(bsd) +define_test(posix)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/tests/test-bsd.c Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,50 @@ +/* + * test-bsd.c -- test BSD extensions + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define _BSD_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <compat.h> + +int +main(void) +{ + int *ints = NULL; + char buf[BUFSIZ]; + char *token, *p; + + pledge("stdio", NULL); + + ints = reallocarray(ints, 5, sizeof (*ints)); + ints = recallocarray(ints, 5, 10, sizeof (*ints)); + + strlcpy(buf, "Hello", sizeof (buf)); + strlcat(buf, " world", sizeof (buf)); + + p = token = buf; + + while ((token = strsep(&p, " \t"))) + printf("%s\n", token); + + free(ints); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/tests/test-dirent.c Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,41 @@ +/* + * dirent.c -- test opendir/readdir + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <dirent.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +int +main(void) +{ + DIR *dp; + struct dirent *entry; + + if (!(dp = opendir(DIRECTORY))) { + fprintf(stderr, "abort: %s\n", strerror(errno)); + return 1; + } + + while ((entry = readdir(dp))) + printf("%s\n", entry->d_name); + + closedir(dp); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/tests/test-dlfcn.c Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,53 @@ +/* + * test-dlfcn.c -- test dlopen/dlsym/dlclose + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <dlfcn.h> +#include <stdio.h> + +#if defined(_WIN32) +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif + +EXPORT int +hello(void) +{ + return 0; +} + +int +main(void) +{ + void *handle; + int (*func)(void); + int ret = 1; + + if (!(handle = dlopen(NULL, RTLD_NOW)) || + !(func = dlsym(handle, "hello"))) { + fprintf(stderr, "%s\n", dlerror()); + goto end; + } + + ret = func(); + + dlclose(handle); + +end: + return ret; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/tests/test-posix.c Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,64 @@ +/* + * test-posix.c -- test POSIX functions + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define _BSD_SOURCE +#include <libgen.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <compat.h> + +int +main(int argc, char **argv) +{ + char path1[FILENAME_MAX] = "/usr/local/bin/vim"; + char path2[FILENAME_MAX] = "/usr/local/bin/vim"; + char tmppath[FILENAME_MAX]; + char *s; + + for (int ch; (ch = getopt(argc, argv, "l:v")) != -1; ) { + switch (ch) { + case 'l': + printf("log level: %s\n", optarg); + break; + case 'v': + printf("verbosity set\n"); + break; + default: + break; + } + } + + s = strdup("Hello World"); + printf("%s\n", s); + free(s); + + s = strndup("Hello World, what's up?", 11); + printf("%s\n", s); + free(s); + + snprintf(tmppath, sizeof (tmppath), "%s", basename(path1)); + puts(tmppath); + + snprintf(tmppath, sizeof (tmppath), "%s", dirname(path1)); + puts(tmppath); + + printf("max len: %zu\n", strnlen("francis", 3)); +}
--- a/extern/libcompat/trycompile.sh Sat Jan 16 09:45:33 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -#!/bin/sh - -prog=$(basename $0) -top=$(dirname $0) -compile=0 -src=$top/src/null.c - -usage() -{ - echo "usage: $prog [-c] function" 1>&2 - exit 1 -} - -code() -{ - cat <<-EOF - void $1(); - - int - main(void) - { - $1(); - } - EOF -} - -var() -{ - printf "$1" | tr "[:lower:]" "[:upper:]" -} - -while getopts "c" opt; do - case $opt in - c) - compile=1 ;; - *) - usage ;; - esac -done - -shift $((OPTIND - 1)) - -if [ $# -eq 0 ]; then - usage -fi - -trap "rm -f test-$1 test-$1.c" QUIT INT TERM EXIT - -code $1 > test-$1.c - -if [ $compile -eq 0 ]; then - printf "Checking for function $1: " -fi - -if ! $CC $CFLAGS -o test-$1 test-$1.c >/dev/null 2>&1; then - if [ $compile -eq 0 ]; then - printf "no\n" - fi - - src=$top/src/$1.c - touch $top/src/$1.h -else - if [ $compile -eq 0 ]; then - printf "yes\n" - fi - - printf "#define COMPAT_HAVE_%s\n" $(var $1) > $top/src/$1.h -fi - -if [ $compile -eq 1 ]; then - $CC $CFLAGS -I $top -c $src -o $top/src/$1.o -fi
--- a/extern/libcompat/tryinclude.sh Sat Jan 16 09:45:33 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -#!/bin/sh - -prog=$(basename $0) -top=$(dirname $0) - -usage() -{ - echo "usage: $prog include" 1>&2 - exit 1 -} - -code() -{ - cat <<-EOF - #include <$1> - - int - main(void) - { - } - EOF -} - -trap "rm -f test-$1 test-$1.c" QUIT INT TERM EXIT - -code $1 > test-$1.c - -printf "Checking for include file $1: " - -if ! $CC $CFLAGS -o test-$1 test-$1.c; then - printf "no\n" - touch $top/include/$1 -else - printf "yes\n" -fi
--- a/extern/libcompat/trylib.sh Sat Jan 16 09:45:33 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -#!/bin/sh - -prog=$(basename $0) -top=$(dirname $0) - -usage() -{ - echo "usage: $prog lib" 1>&2 - exit 1 -} - -code() -{ - cat <<-EOF - int - main(void) - { - } - EOF -} - -lib() -{ - printf "$1" | sed 's|^lib||;s|\.a||' -} - -name=$(lib $1) - -trap "rm -f test-$name test-$name.c" QUIT INT TERM EXIT - -code > test-$name.c - -printf "Checking for library $name: " - -if ! $CC $CFLAGS -o test-$name test-$name.c $LDFLAGS -l$name; then - printf "no\n" - $CC $CFLAGS -c $top/src/null.c -o $top/src/null.o - $AR -rc $top/lib/lib$name.a $top/src/null.o - rm -f $top/src/null.o -else - printf "yes\n" -fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/win/dirent/dirent.h Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,1027 @@ +/* + * Dirent interface for Microsoft Visual Studio + * + * Copyright (C) 1998-2019 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* Hide warnings about unreferenced local functions */ +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#elif defined(_MSC_VER) +# pragma warning(disable:4505) +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +#include <stdio.h> +#include <stdarg.h> +#include <wchar.h> +#include <string.h> +#include <stdlib.h> +#include <malloc.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <ctype.h> + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of the file name without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return the maximum size of a file name */ +#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX+1]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +/* Multi-byte character version */ +struct dirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX+1]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + + +/* Dirent functions */ +static DIR *opendir(const char *dirname); +static _WDIR *_wopendir(const wchar_t *dirname); + +static struct dirent *readdir(DIR *dirp); +static struct _wdirent *_wreaddir(_WDIR *dirp); + +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result); +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); + +static int closedir(DIR *dirp); +static int _wclosedir(_WDIR *dirp); + +static void rewinddir(DIR* dirp); +static void _wrewinddir(_WDIR* dirp); + +static int scandir(const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)); + +static int alphasort(const struct dirent **a, const struct dirent **b); + +static int versionsort(const struct dirent **a, const struct dirent **b); + +static int strverscmp(const char *a, const char *b); + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + +/* Compatibility with older Microsoft compilers and non-Microsoft compilers */ +#if !defined(_MSC_VER) || _MSC_VER < 1400 +# define wcstombs_s dirent_wcstombs_s +# define mbstowcs_s dirent_mbstowcs_s +#endif + +/* Optimize dirent_set_errno() away on modern Microsoft compilers */ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# define dirent_set_errno _set_errno +#endif + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); + +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static int dirent_mbstowcs_s( + size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, + const char *mbstr, size_t count); +#endif + +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static int dirent_wcstombs_s( + size_t *pReturnValue, char *mbstr, size_t sizeInBytes, + const wchar_t *wcstr, size_t count); +#endif + +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static void dirent_set_errno(int error); +#endif + + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR *_wopendir(const wchar_t *dirname) +{ + wchar_t *p; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + _WDIR *dirp = (_WDIR*) malloc(sizeof(struct _WDIR)); + if (!dirp) + return NULL; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* + * Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + DWORD n = GetFullPathNameW(dirname, 0, NULL, NULL); +#else + /* WinRT */ + size_t n = wcslen(dirname); +#endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc(sizeof(wchar_t) * n + 16); + if (dirp->patt == NULL) + goto exit_closedir; + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW(dirname, n, dirp->patt, NULL); + if (n <= 0) + goto exit_closedir; +#else + /* WinRT */ + wcsncpy_s(dirp->patt, n+1, dirname, n); +#endif + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (!dirent_first(dirp)) + goto exit_closedir; + + /* Success */ + return dirp; + + /* Failure */ +exit_closedir: + _wclosedir(dirp); + return NULL; +} + +/* + * Read next directory entry. + * + * Returns pointer to static directory entry which may be overwritten by + * subsequent calls to _wreaddir(). + */ +static struct _wdirent *_wreaddir(_WDIR *dirp) +{ + /* + * Read directory entry to buffer. We can safely ignore the return + * value as entry will be set to NULL in case of error. + */ + struct _wdirent *entry; + (void) _wreaddir_r(dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry. + * + * Returns zero on success. If end of directory stream is reached, then sets + * result to NULL and returns zero. + */ +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result) +{ + /* Read next directory entry */ + WIN32_FIND_DATAW *datap = dirent_next(dirp); + if (!datap) { + /* Return NULL to indicate end of directory */ + *result = NULL; + return /*OK*/0; + } + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + size_t n = 0; + while (n < PATH_MAX && datap->cFileName[n] != 0) { + entry->d_name[n] = datap->cFileName[n]; + n++; + } + entry->d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n; + + /* File type */ + DWORD attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) + entry->d_type = DT_CHR; + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + entry->d_type = DT_DIR; + else + entry->d_type = DT_REG; + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof(struct _wdirent); + + /* Set result address */ + *result = entry; + return /*OK*/0; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int _wclosedir(_WDIR *dirp) +{ + if (!dirp) { + dirent_set_errno(EBADF); + return /*failure*/-1; + } + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) + FindClose(dirp->handle); + + /* Release search pattern */ + free(dirp->patt); + + /* Release directory structure */ + free(dirp); + return /*success*/0; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void _wrewinddir(_WDIR* dirp) +{ + if (!dirp) + return; + + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) + FindClose(dirp->handle); + + /* Open new search handle */ + dirent_first(dirp); +} + +/* Get first directory entry */ +static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp) +{ + if (!dirp) + return NULL; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle == INVALID_HANDLE_VALUE) + goto error; + + /* A directory entry is now waiting in memory */ + dirp->cached = 1; + return &dirp->data; + +error: + /* Failed to open directory: no directory entry in memory */ + dirp->cached = 0; + + /* Set error code */ + DWORD errorcode = GetLastError(); + switch (errorcode) { + case ERROR_ACCESS_DENIED: + /* No read access to directory */ + dirent_set_errno(EACCES); + break; + + case ERROR_DIRECTORY: + /* Directory name is invalid */ + dirent_set_errno(ENOTDIR); + break; + + case ERROR_PATH_NOT_FOUND: + default: + /* Cannot find the file */ + dirent_set_errno(ENOENT); + } + return NULL; +} + +/* Get next directory entry */ +static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp) +{ + /* Is the next directory entry already in cache? */ + if (dirp->cached) { + /* Yes, a valid directory entry found in memory */ + dirp->cached = 0; + return &dirp->data; + } + + /* No directory entry in cache */ + if (dirp->handle == INVALID_HANDLE_VALUE) + return NULL; + + /* Read the next directory entry from stream */ + if (FindNextFileW(dirp->handle, &dirp->data) == FALSE) + goto exit_close; + + /* Success */ + return &dirp->data; + + /* Failure */ +exit_close: + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + return NULL; +} + +/* Open directory stream using plain old C-string */ +static DIR *opendir(const char *dirname) +{ + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + struct DIR *dirp = (DIR*) malloc(sizeof(struct DIR)); + if (!dirp) + return NULL; + + /* Convert directory name to wide-character string */ + wchar_t wname[PATH_MAX + 1]; + size_t n; + int error = mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX+1); + if (error) + goto exit_failure; + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir(wname); + if (!dirp->wdirp) + goto exit_failure; + + /* Success */ + return dirp; + + /* Failure */ +exit_failure: + free(dirp); + return NULL; +} + +/* Read next directory entry */ +static struct dirent *readdir(DIR *dirp) +{ + /* + * Read directory entry to buffer. We can safely ignore the return + * value as entry will be set to NULL in case of error. + */ + struct dirent *entry; + (void) readdir_r(dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry into called-allocated buffer. + * + * Returns zero on success. If the end of directory stream is reached, then + * sets result to NULL and returns zero. + */ +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result) +{ + /* Read next directory entry */ + WIN32_FIND_DATAW *datap = dirent_next(dirp->wdirp); + if (!datap) { + /* No more directory entries */ + *result = NULL; + return /*OK*/0; + } + + /* Attempt to convert file name to multi-byte string */ + size_t n; + int error = wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cFileName, PATH_MAX + 1); + + /* + * If the file name cannot be represented by a multi-byte string, then + * attempt to use old 8+3 file name. This allows the program to + * access files although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file name + * unless the file system provides one. At least VirtualBox shared + * folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cAlternateFileName, PATH_MAX + 1); + } + + if (!error) { + /* Length of file name excluding zero terminator */ + entry->d_namlen = n - 1; + + /* File attributes */ + DWORD attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) + entry->d_type = DT_CHR; + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + entry->d_type = DT_DIR; + else + entry->d_type = DT_REG; + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof(struct dirent); + } else { + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entry->d_name[0] = '?'; + entry->d_name[1] = '\0'; + entry->d_namlen = 1; + entry->d_type = DT_UNKNOWN; + entry->d_ino = 0; + entry->d_off = -1; + entry->d_reclen = 0; + } + + /* Return pointer to directory entry */ + *result = entry; + return /*OK*/0; +} + +/* Close directory stream */ +static int closedir(DIR *dirp) +{ + int ok; + + if (!dirp) + goto exit_failure; + + /* Close wide-character directory stream */ + ok = _wclosedir(dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free(dirp); + return ok; + +exit_failure: + /* Invalid directory stream */ + dirent_set_errno(EBADF); + return /*failure*/-1; +} + +/* Rewind directory stream to beginning */ +static void rewinddir(DIR* dirp) +{ + if (!dirp) + return; + + /* Rewind wide-character string directory stream */ + _wrewinddir(dirp->wdirp); +} + +/* Scan directory for entries */ +static int scandir( + const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)) +{ + int result; + + /* Open directory stream */ + DIR *dir = opendir(dirname); + if (!dir) { + /* Cannot open directory */ + return /*Error*/ -1; + } + + /* Read directory entries to memory */ + struct dirent *tmp = NULL; + struct dirent **files = NULL; + size_t size = 0; + size_t allocated = 0; + while (1) { + /* Allocate room for a temporary directory entry */ + if (!tmp) { + tmp = (struct dirent*) malloc(sizeof(struct dirent)); + if (!tmp) + goto exit_failure; + } + + /* Read directory entry to temporary area */ + struct dirent *entry; + if (readdir_r(dir, tmp, &entry) != /*OK*/0) + goto exit_failure; + + /* Stop if we already read the last directory entry */ + if (entry == NULL) + goto exit_success; + + /* Determine whether to include the entry in results */ + if (filter && !filter(tmp)) + continue; + + /* Enlarge pointer table to make room for another pointer */ + if (size >= allocated) { + /* Compute number of entries in the new table */ + size_t num_entries = size * 2 + 16; + + /* Allocate new pointer table or enlarge existing */ + void *p = realloc(files, sizeof(void*) * num_entries); + if (!p) + goto exit_failure; + + /* Got the memory */ + files = (dirent**) p; + allocated = num_entries; + } + + /* Store the temporary entry to ptr table */ + files[size++] = tmp; + tmp = NULL; + } + +exit_failure: + /* Release allocated file entries */ + for (size_t i = 0; i < size; i++) { + free(files[i]); + } + + /* Release the pointer table */ + free(files); + files = NULL; + + /* Exit with error code */ + result = /*error*/ -1; + goto exit_status; + +exit_success: + /* Sort directory entries */ + qsort(files, size, sizeof(void*), + (int (*) (const void*, const void*)) compare); + + /* Pass pointer table to caller */ + if (namelist) + *namelist = files; + + /* Return the number of directory entries read */ + result = (int) size; + +exit_status: + /* Release temporary directory entry, if we had one */ + free(tmp); + + /* Close directory stream */ + closedir(dir); + return result; +} + +/* Alphabetical sorting */ +static int alphasort(const struct dirent **a, const struct dirent **b) +{ + return strcoll((*a)->d_name, (*b)->d_name); +} + +/* Sort versions */ +static int versionsort(const struct dirent **a, const struct dirent **b) +{ + return strverscmp((*a)->d_name, (*b)->d_name); +} + +/* Compare strings */ +static int strverscmp(const char *a, const char *b) +{ + size_t i = 0; + size_t j; + + /* Find first difference */ + while (a[i] == b[i]) { + if (a[i] == '\0') { + /* No difference */ + return 0; + } + ++i; + } + + /* Count backwards and find the leftmost digit */ + j = i; + while (j > 0 && isdigit(a[j-1])) { + --j; + } + + /* Determine mode of comparison */ + if (a[j] == '0' || b[j] == '0') { + /* Find the next non-zero digit */ + while (a[j] == '0' && a[j] == b[j]) { + j++; + } + + /* String with more digits is smaller, e.g 002 < 01 */ + if (isdigit(a[j])) { + if (!isdigit(b[j])) { + return -1; + } + } else if (isdigit(b[j])) { + return 1; + } + } else if (isdigit(a[j]) && isdigit(b[j])) { + /* Numeric comparison */ + size_t k1 = j; + size_t k2 = j; + + /* Compute number of digits in each string */ + while (isdigit(a[k1])) { + k1++; + } + while (isdigit(b[k2])) { + k2++; + } + + /* Number with more digits is bigger, e.g 999 < 1000 */ + if (k1 < k2) + return -1; + else if (k1 > k2) + return 1; + } + + /* Alphabetical comparison */ + return (int) ((unsigned char) a[i]) - ((unsigned char) b[i]); +} + +/* Convert multi-byte string to wide character string */ +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static int dirent_mbstowcs_s( + size_t *pReturnValue, wchar_t *wcstr, + size_t sizeInWords, const char *mbstr, size_t count) +{ + /* Older Visual Studio or non-Microsoft compiler */ + size_t n = mbstowcs(wcstr, mbstr, sizeInWords); + if (wcstr && n >= count) + return /*error*/ 1; + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) + n = sizeInWords - 1; + wcstr[n] = 0; + } + + /* Length of multi-byte string with zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + return 0; +} +#endif + +/* Convert wide-character string to multi-byte string */ +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static int dirent_wcstombs_s( + size_t *pReturnValue, char *mbstr, + size_t sizeInBytes, const wchar_t *wcstr, size_t count) +{ + /* Older Visual Studio or non-Microsoft compiler */ + size_t n = wcstombs(mbstr, wcstr, sizeInBytes); + if (mbstr && n >= count) + return /*error*/1; + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + return 0; +} +#endif + +/* Set errno variable */ +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static void dirent_set_errno(int error) +{ + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; +} +#endif + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/win/dlfcn/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,26 @@ +project(dl) +add_library( + dl + STATIC + ${dl_SOURCE_DIR}/dlfcn.h + ${dl_SOURCE_DIR}/dlfcn.c +) + +# Correctly export the location of installed includes in the target +target_include_directories( + dl + PUBLIC + $<BUILD_INTERFACE:${dl_SOURCE_DIR}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> +) + +if (CMAKE_C_COMPILER_ID MATCHES "MSVC") + target_compile_definitions(dl PRIVATE _CRT_SECURE_NO_WARNINGS) +endif () + +install( + TARGETS dl + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/win/dlfcn/dlfcn.c Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,478 @@ +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * Copyright (c) 2015 Tiancheng "Timothy" Gu + * Copyright (c) 2019 Pali Rohár <pali.rohar@gmail.com> + * + * 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. + */ + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#ifdef _DEBUG +#define _CRTDBG_MAP_ALLOC +#include <stdlib.h> +#include <crtdbg.h> +#endif +#include <windows.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef _MSC_VER +/* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ +#pragma intrinsic(_ReturnAddress) +#else +/* https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html */ +#ifndef _ReturnAddress +#define _ReturnAddress() (__builtin_extract_return_addr(__builtin_return_address(0))) +#endif +#endif + +#ifdef SHARED +#define DLFCN_WIN32_EXPORTS +#endif +#include "dlfcn.h" + +/* Note: + * MSDN says these functions are not thread-safe. We make no efforts to have + * any kind of thread safety. + */ + +typedef struct local_object { + HMODULE hModule; + struct local_object *previous; + struct local_object *next; +} local_object; + +static local_object first_object; + +/* These functions implement a double linked list for the local objects. */ +static local_object *local_search( HMODULE hModule ) +{ + local_object *pobject; + + if( hModule == NULL ) + return NULL; + + for( pobject = &first_object; pobject; pobject = pobject->next ) + if( pobject->hModule == hModule ) + return pobject; + + return NULL; +} + +static BOOL local_add( HMODULE hModule ) +{ + local_object *pobject; + local_object *nobject; + + if( hModule == NULL ) + return TRUE; + + pobject = local_search( hModule ); + + /* Do not add object again if it's already on the list */ + if( pobject ) + return TRUE; + + for( pobject = &first_object; pobject->next; pobject = pobject->next ); + + nobject = (local_object*) malloc( sizeof( local_object ) ); + + if( !nobject ) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + pobject->next = nobject; + nobject->next = NULL; + nobject->previous = pobject; + nobject->hModule = hModule; + + return TRUE; +} + +static void local_rem( HMODULE hModule ) +{ + local_object *pobject; + + if( hModule == NULL ) + return; + + pobject = local_search( hModule ); + + if( !pobject ) + return; + + if( pobject->next ) + pobject->next->previous = pobject->previous; + if( pobject->previous ) + pobject->previous->next = pobject->next; + + free( pobject ); +} + +/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one + * static buffer. + * MSDN says the buffer cannot be larger than 64K bytes, so we set it to + * the limit. + */ +static char error_buffer[65535]; +static BOOL error_occurred; + +static void save_err_str( const char *str ) +{ + DWORD dwMessageId; + DWORD ret; + size_t pos, len; + + dwMessageId = GetLastError( ); + + if( dwMessageId == 0 ) + return; + + len = strlen( str ); + if( len > sizeof( error_buffer ) - 5 ) + len = sizeof( error_buffer ) - 5; + + /* Format error message to: + * "<argument to function that failed>": <Windows localized error message> + */ + pos = 0; + error_buffer[pos++] = '"'; + memcpy( error_buffer+pos, str, len ); + pos += len; + error_buffer[pos++] = '"'; + error_buffer[pos++] = ':'; + error_buffer[pos++] = ' '; + + ret = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwMessageId, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + error_buffer+pos, (DWORD) (sizeof(error_buffer)-pos), NULL ); + pos += ret; + + /* When FormatMessageA() fails it returns zero and does not touch buffer + * so add trailing null byte */ + if( ret == 0 ) + error_buffer[pos] = '\0'; + + if( pos > 1 ) + { + /* POSIX says the string must not have trailing <newline> */ + if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' ) + error_buffer[pos-2] = '\0'; + } + + error_occurred = TRUE; +} + +static void save_err_ptr_str( const void *ptr ) +{ + char ptr_buf[19]; /* 0x<pointer> up to 64 bits. */ + +#ifdef _MSC_VER +/* Supress warning C4996: 'sprintf': This function or variable may be unsafe */ +#pragma warning( suppress: 4996 ) +#endif + sprintf( ptr_buf, "0x%p", ptr ); + + save_err_str( ptr_buf ); +} + +/* Load Psapi.dll at runtime, this avoids linking caveat */ +static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ) +{ + static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD); + HMODULE psapi; + + if( !EnumProcessModulesPtr ) + { + psapi = LoadLibraryA( "Psapi.dll" ); + if( psapi ) + EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( psapi, "EnumProcessModules" ); + if( !EnumProcessModulesPtr ) + return 0; + } + + return EnumProcessModulesPtr( hProcess, lphModule, cb, lpcbNeeded ); +} + +void *dlopen( const char *file, int mode ) +{ + HMODULE hModule; + UINT uMode; + + error_occurred = FALSE; + + /* Do not let Windows display the critical-error-handler message box */ + uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); + + if( file == 0 ) + { + /* POSIX says that if the value of file is 0, a handle on a global + * symbol object must be provided. That object must be able to access + * all symbols from the original program file, and any objects loaded + * with the RTLD_GLOBAL flag. + * The return value from GetModuleHandle( ) allows us to retrieve + * symbols only from the original program file. EnumProcessModules() is + * used to access symbols from other libraries. For objects loaded + * with the RTLD_LOCAL flag, we create our own list later on. They are + * excluded from EnumProcessModules() iteration. + */ + hModule = GetModuleHandle( NULL ); + + if( !hModule ) + save_err_str( "(null)" ); + } + else + { + HANDLE hCurrentProc; + DWORD dwProcModsBefore, dwProcModsAfter; + char lpFileName[MAX_PATH]; + size_t i, len; + + len = strlen( file ); + + if( len >= sizeof( lpFileName ) ) + { + SetLastError( ERROR_FILENAME_EXCED_RANGE ); + save_err_str( file ); + hModule = NULL; + } + else + { + /* MSDN says backslashes *must* be used instead of forward slashes. */ + for( i = 0; i < len; i++ ) + { + if( file[i] == '/' ) + lpFileName[i] = '\\'; + else + lpFileName[i] = file[i]; + } + lpFileName[len] = '\0'; + + hCurrentProc = GetCurrentProcess( ); + + if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 ) + dwProcModsBefore = 0; + + /* POSIX says the search path is implementation-defined. + * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely + * to UNIX's search paths (start with system folders instead of current + * folder). + */ + hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); + + if( !hModule ) + { + save_err_str( lpFileName ); + } + else + { + if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 ) + dwProcModsAfter = 0; + + /* If the object was loaded with RTLD_LOCAL, add it to list of local + * objects, so that its symbols cannot be retrieved even if the handle for + * the original program file is passed. POSIX says that if the same + * file is specified in multiple invocations, and any of them are + * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the + * symbols will remain global. If number of loaded modules was not + * changed after calling LoadLibraryEx(), it means that library was + * already loaded. + */ + if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter ) + { + if( !local_add( hModule ) ) + { + save_err_str( lpFileName ); + FreeLibrary( hModule ); + hModule = NULL; + } + } + else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter ) + { + local_rem( hModule ); + } + } + } + } + + /* Return to previous state of the error-mode bit flags. */ + SetErrorMode( uMode ); + + return (void *) hModule; +} + +int dlclose( void *handle ) +{ + HMODULE hModule = (HMODULE) handle; + BOOL ret; + + error_occurred = FALSE; + + ret = FreeLibrary( hModule ); + + /* If the object was loaded with RTLD_LOCAL, remove it from list of local + * objects. + */ + if( ret ) + local_rem( hModule ); + else + save_err_ptr_str( handle ); + + /* dlclose's return value in inverted in relation to FreeLibrary's. */ + ret = !ret; + + return (int) ret; +} + +__declspec(noinline) /* Needed for _ReturnAddress() */ +void *dlsym( void *handle, const char *name ) +{ + FARPROC symbol; + HMODULE hCaller; + HMODULE hModule; + HANDLE hCurrentProc; + + error_occurred = FALSE; + + symbol = NULL; + hCaller = NULL; + hModule = GetModuleHandle( NULL ); + hCurrentProc = GetCurrentProcess( ); + + if( handle == RTLD_DEFAULT ) + { + /* The symbol lookup happens in the normal global scope; that is, + * a search for a symbol using this handle would find the same + * definition as a direct use of this symbol in the program code. + * So use same lookup procedure as when filename is NULL. + */ + handle = hModule; + } + else if( handle == RTLD_NEXT ) + { + /* Specifies the next object after this one that defines name. + * This one refers to the object containing the invocation of dlsym(). + * The next object is the one found upon the application of a load + * order symbol resolution algorithm. To get caller function of dlsym() + * use _ReturnAddress() intrinsic. To get HMODULE of caller function + * use standard GetModuleHandleExA() function. + */ + if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) _ReturnAddress( ), &hCaller ) ) + goto end; + } + + if( handle != RTLD_NEXT ) + { + symbol = GetProcAddress( (HMODULE) handle, name ); + + if( symbol != NULL ) + goto end; + } + + /* If the handle for the original program file is passed, also search + * in all globally loaded objects. + */ + + if( hModule == handle || handle == RTLD_NEXT ) + { + HMODULE *modules; + DWORD cbNeeded; + DWORD dwSize; + size_t i; + + /* GetModuleHandle( NULL ) only returns the current program file. So + * if we want to get ALL loaded module including those in linked DLLs, + * we have to use EnumProcessModules( ). + */ + if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwSize ) != 0 ) + { + modules = malloc( dwSize ); + if( modules ) + { + if( MyEnumProcessModules( hCurrentProc, modules, dwSize, &cbNeeded ) != 0 && dwSize == cbNeeded ) + { + for( i = 0; i < dwSize / sizeof( HMODULE ); i++ ) + { + if( handle == RTLD_NEXT && hCaller ) + { + /* Next modules can be used for RTLD_NEXT */ + if( hCaller == modules[i] ) + hCaller = NULL; + continue; + } + if( local_search( modules[i] ) ) + continue; + symbol = GetProcAddress( modules[i], name ); + if( symbol != NULL ) + { + free( modules ); + goto end; + } + } + + } + free( modules ); + } + else + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + goto end; + } + } + } + +end: + if( symbol == NULL ) + { + if( GetLastError() == 0 ) + SetLastError( ERROR_PROC_NOT_FOUND ); + save_err_str( name ); + } + + return *(void **) (&symbol); +} + +char *dlerror( void ) +{ + /* If this is the second consecutive call to dlerror, return NULL */ + if( !error_occurred ) + return NULL; + + /* POSIX says that invoking dlerror( ) a second time, immediately following + * a prior invocation, shall result in NULL being returned. + */ + error_occurred = FALSE; + + return error_buffer; +} + +#ifdef SHARED +BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) +{ + (void) hinstDLL; + (void) fdwReason; + (void) lpvReserved; + return TRUE; +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libcompat/win/dlfcn/dlfcn.h Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,78 @@ +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * + * 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. + */ + +#ifndef DLFCN_H +#define DLFCN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DLFCN_BUILD_DLL) +# define DLFCN_EXPORT __declspec(dllexport) +#else +# define DLFCN_EXPORT +#endif + +/* Relocations are performed when the object is loaded. */ +#define RTLD_NOW 0 + +/* Relocations are performed at an implementation-defined time. + * Windows API does not support lazy symbol resolving (when first reference + * to a given symbol occurs). So RTLD_LAZY implementation is same as RTLD_NOW. + */ +#define RTLD_LAZY RTLD_NOW + +/* All symbols are available for relocation processing of other modules. */ +#define RTLD_GLOBAL (1 << 1) + +/* All symbols are not made available for relocation processing by other modules. */ +#define RTLD_LOCAL (1 << 2) + +/* These two were added in The Open Group Base Specifications Issue 6. + * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. + */ + +/* The symbol lookup happens in the normal global scope. */ +#define RTLD_DEFAULT ((void *)0) + +/* Specifies the next object after this one that defines name. */ +#define RTLD_NEXT ((void *)-1) + +/* Open a symbol table handle. */ +DLFCN_EXPORT void *dlopen(const char *file, int mode); + +/* Close a symbol table handle. */ +DLFCN_EXPORT int dlclose(void *handle); + +/* Get the address of a symbol from a symbol table handle. */ +DLFCN_EXPORT void *dlsym(void *handle, const char *name); + +/* Get diagnostic information. */ +DLFCN_EXPORT char *dlerror(void); + +#ifdef __cplusplus +} +#endif + +#endif /* DLFCN_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/libduktape/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,31 @@ +# +# CMakeLists.txt -- CMake build system for duktape +# +# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +cmake_minimum_required(VERSION 3.0) +project(libirccd-duktape) +add_library(libirccd-duktape duk_config.h duktape.c duktape.h) +target_include_directories( + libirccd-duktape + PUBLIC + $<BUILD_INTERFACE:${libirccd-duktape_SOURCE_DIR}> +) +if (BUILD_SHARED_LIBS) + target_compile_definitions(libirccd-duktape PUBLIC DUK_F_DLL_BUILD) +endif () + +set_target_properties(libirccd-duktape PROPERTIES PREFIX "")
--- a/extern/libduktape/Makefile Sat Jan 16 09:45:33 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -# -# Makefile -- POSIX makefile for irccd -# -# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -include ../../config.mk - -all: libirccd-duktape.a - -duktape.o: duktape.c duktape.h duk_config.h - ${CC} ${CFLAGS} -c $< -o $@ - -libirccd-duktape.a: duktape.o - ${CMD.ar} - -clean: - rm -f libirccd-duktape.a duktape.o - -.PHONY: clean
--- a/extern/libgreatest/CMakeLists.txt Sat Jan 16 09:45:33 2021 +0100 +++ b/extern/libgreatest/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -17,11 +17,11 @@ # cmake_minimum_required(VERSION 3.0) -project(libgreatest) -add_library(libgreatest INTERFACE) +project(libirccd-greatest) +add_library(libirccd-greatest INTERFACE) target_include_directories( - libgreatest + libirccd-greatest INTERFACE - $<BUILD_INTERFACE:${libgreatest_SOURCE_DIR}> + $<BUILD_INTERFACE:${libirccd-greatest_SOURCE_DIR}> ) -target_sources(libgreatest INTERFACE ${libgreatest_SOURCE_DIR}/greatest.h) +target_sources(libirccd-greatest INTERFACE ${libirccd-greatest_SOURCE_DIR}/greatest.h)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/irccd/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,21 @@ +# +# CMakeLists.txt -- CMake build for irccd +# +# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(irccd) +add_executable(irccd main.c) +target_link_libraries(irccd libirccd)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/irccdctl/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,21 @@ +# +# CMakeLists.txt -- CMake build for irccd +# +# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(irccdctl) +add_executable(irccdctl main.c) +target_link_libraries(irccdctl libirccd)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,100 @@ +# +# CMakeLists.txt -- CMake build for irccd +# +# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(libirccd) + +set( + SOURCES + CMakeLists.txt + irccd/channel.c + irccd/channel.h + irccd/config.h.in + irccd/dl-plugin.c + irccd/dl-plugin.h + irccd/event.h + irccd/irccd.c + irccd/irccd.h + irccd/limits.h + irccd/log.c + irccd/log.h + irccd/peer.c + irccd/peer.h + irccd/plugin.c + irccd/plugin.h + irccd/rule.c + irccd/rule.h + irccd/server.c + irccd/server.h + irccd/set.h + irccd/subst.c + irccd/subst.h + irccd/transport.c + irccd/transport.h + irccd/util.c + irccd/util.h +) + +if (IRCCD_WITH_JS) + list( + APPEND SOURCES + irccd/unicode.c + irccd/unicode.h + irccd/js-plugin.c + irccd/js-plugin.h + irccd/jsapi-chrono.c + irccd/jsapi-chrono.h + irccd/jsapi-file.c + irccd/jsapi-file.h + irccd/jsapi-irccd.c + irccd/jsapi-irccd.h + irccd/jsapi-logger.c + irccd/jsapi-logger.h + irccd/jsapi-plugin.c + irccd/jsapi-plugin.h + irccd/jsapi-server.c + irccd/jsapi-server.h + irccd/jsapi-system.c + irccd/jsapi-system.h + irccd/jsapi-timer.c + irccd/jsapi-timer.h + irccd/jsapi-unicode.c + irccd/jsapi-unicode.h + ) +endif () + +configure_file( + ${libirccd_SOURCE_DIR}/irccd/config.h.in + ${libirccd_BINARY_DIR}/irccd/config.h +) + +add_library(libirccd ${SOURCES}) +set_target_properties(libirccd PROPERTIES PREFIX "") + +target_include_directories( + libirccd + PUBLIC + $<BUILD_INTERFACE:${libirccd_SOURCE_DIR}> + $<BUILD_INTERFACE:${libirccd_BINARY_DIR}> + PRIVATE + $<BUILD_INTERFACE:${libirccd_BINARY_DIR}>/irccd +) +target_link_libraries(libirccd libirccd-compat) + +if (IRCCD_WITH_JS) + target_link_libraries(libirccd libirccd-duktape) +endif ()
--- a/lib/irccd/config.h.in Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/config.h.in Sat Jan 16 17:58:46 2021 +0100 @@ -5,7 +5,7 @@ #define IRCCD_VERSION_MINOR @IRCCD_VERSION_MINOR@ #define IRCCD_VERSION_PATCH @IRCCD_VERSION_PATCH@ -#define IRCCD_WITH_JS -#define IRCCD_WITH_SSL +#cmakedefine IRCCD_WITH_JS +#cmakedefine IRCCD_WITH_SSL #endif /* !IRCCD_CONFIG_H */
--- a/lib/irccd/irccd.c Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/irccd.c Sat Jan 16 17:58:46 2021 +0100 @@ -50,12 +50,6 @@ static int pipes[2]; static int -cmp_server(const struct irc_server *s1, const struct irc_server *s2) -{ - return strcmp(s1->name, s2->name); -} - -static int cmp_plugin(const struct irc_plugin *p1, const struct irc_plugin *p2) { return strcmp(p1->name, p2->name);
--- a/lib/irccd/js-plugin.c Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/js-plugin.c Sat Jan 16 17:58:46 2021 +0100 @@ -453,7 +453,6 @@ assert(plg); assert(path); - bool ret = false; char *script = NULL; if (!(script = eat(path))) {
--- a/lib/irccd/jsapi-file.c Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/jsapi-file.c Sat Jan 16 17:58:46 2021 +0100 @@ -25,6 +25,7 @@ #include <duktape.h> +#include "compat.h" #include "jsapi-file.h" #include "jsapi-system.h" #include "util.h" @@ -96,56 +97,56 @@ { duk_push_object(ctx); -#if defined(IRCCD_HAVE_STAT_ST_ATIME) - duk_push_int(ctx, st.st_atime); +#if defined(COMPAT_HAVE_STAT_ST_ATIME) + duk_push_int(ctx, st->st_atime); duk_put_prop_string(ctx, -2, "atime"); #endif -#if defined(IRCCD_HAVE_STAT_ST_BLKSIZE) - duk_push_int(ctx, st.st_blksize); +#if defined(COMPAT_HAVE_STAT_ST_BLKSIZE) + duk_push_int(ctx, st->st_blksize); duk_put_prop_string(ctx, -2, "blksize"); #endif -#if defined(IRCCD_HAVE_STAT_ST_BLOCKS) - duk_push_int(ctx, st.st_blocks); +#if defined(COMPAT_HAVE_STAT_ST_BLOCKS) + duk_push_int(ctx, st->st_blocks); duk_put_prop_string(ctx, -2, "blocks"); #endif -#if defined(IRCCD_HAVE_STAT_ST_CTIME) - duk_push_int(ctx, st.st_ctime); +#if defined(COMPAT_HAVE_STAT_ST_CTIME) + duk_push_int(ctx, st->st_ctime); duk_put_prop_string(ctx, -2, "ctime"); #endif -#if defined(IRCCD_HAVE_STAT_ST_DEV) - duk_push_int(ctx, st.st_dev); +#if defined(COMPAT_HAVE_STAT_ST_DEV) + duk_push_int(ctx, st->st_dev); duk_put_prop_string(ctx, -2, "dev"); #endif -#if defined(IRCCD_HAVE_STAT_ST_GID) - duk_push_int(ctx, st.st_gid); +#if defined(COMPAT_HAVE_STAT_ST_GID) + duk_push_int(ctx, st->st_gid); duk_put_prop_string(ctx, -2, "gid"); #endif -#if defined(IRCCD_HAVE_STAT_ST_INO) - duk_push_int(ctx, st.st_ino); +#if defined(COMPAT_HAVE_STAT_ST_INO) + duk_push_int(ctx, st->st_ino); duk_put_prop_string(ctx, -2, "ino"); #endif -#if defined(IRCCD_HAVE_STAT_ST_MODE) - duk_push_int(ctx, st.st_mode); +#if defined(COMPAT_HAVE_STAT_ST_MODE) + duk_push_int(ctx, st->st_mode); duk_put_prop_string(ctx, -2, "mode"); #endif -#if defined(IRCCD_HAVE_STAT_ST_MTIME) - duk_push_int(ctx, st.st_mtime); +#if defined(COMPAT_HAVE_STAT_ST_MTIME) + duk_push_int(ctx, st->st_mtime); duk_put_prop_string(ctx, -2, "mtime"); #endif -#if defined(IRCCD_HAVE_STAT_ST_NLINK) - duk_push_int(ctx, st.st_nlink); +#if defined(COMPAT_HAVE_STAT_ST_NLINK) + duk_push_int(ctx, st->st_nlink); duk_put_prop_string(ctx, -2, "nlink"); #endif -#if defined(IRCCD_HAVE_STAT_ST_RDEV) - duk_push_int(ctx, st.st_rdev); +#if defined(COMPAT_HAVE_STAT_ST_RDEV) + duk_push_int(ctx, st->st_rdev); duk_put_prop_string(ctx, -2, "rdev"); #endif -#if defined(IRCCD_HAVE_STAT_ST_SIZE) - duk_push_int(ctx, st.st_size); +#if defined(COMPAT_HAVE_STAT_ST_SIZE) + duk_push_int(ctx, st->st_size); duk_put_prop_string(ctx, -2, "size"); #endif -#if defined(IRCCD_HAVE_STAT_ST_UID) - duk_push_int(ctx, st.st_uid); +#if defined(COMPAT_HAVE_STAT_ST_UID) + duk_push_int(ctx, st->st_uid); duk_put_prop_string(ctx, -2, "uid"); #endif } @@ -239,7 +240,7 @@ irc_jsapi_system_raise(ctx); } - return amount == -1 + return amount == -1U ? read_until_eof(ctx, file) : read_amount(ctx, file, amount); }
--- a/lib/irccd/jsapi-plugin.c Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/jsapi-plugin.c Sat Jan 16 17:58:46 2021 +0100 @@ -172,18 +172,24 @@ static duk_ret_t Plugin_load(duk_context *ctx) { + (void)ctx; + return 0; } static duk_ret_t Plugin_reload(duk_context *ctx) { + (void)ctx; + return 0; } static duk_ret_t Plugin_unload(duk_context *ctx) { + (void)ctx; + return 0; }
--- a/lib/irccd/jsapi-server.c Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/jsapi-server.c Sat Jan 16 17:58:46 2021 +0100 @@ -136,6 +136,7 @@ static duk_ret_t Server_prototype_isSelf(duk_context *ctx) { + (void)ctx; #if 0 return wrap(ctx, [] (auto ctx) { return duk::push(ctx, self(ctx)->is_self(duk::require<std::string>(ctx, 0))); @@ -340,9 +341,7 @@ static duk_ret_t Server_prototype_whois(duk_context *ctx) { - struct irc_server *s = self(ctx); - const char *target = duk_require_string(ctx, 0); - + (void)ctx; #if 0 if (target.empty()) throw server_error(server_error::invalid_nickname); @@ -474,6 +473,8 @@ return 0; } +#if 0 + static duk_ret_t Server_destructor(duk_context *ctx) { @@ -490,11 +491,15 @@ return 0; } +#endif + static duk_ret_t Server_add(duk_context *ctx) { struct irc_server *sv = require(ctx, 0); + irc_bot_add_server(sv); + return 0; }
--- a/lib/irccd/jsapi-system.c Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/jsapi-system.c Sat Jan 16 17:58:46 2021 +0100 @@ -226,7 +226,7 @@ { NULL, NULL, 0 } }; -void +void noreturn irc_jsapi_system_raise(duk_context *ctx) { duk_get_global_string(ctx, "Irccd");
--- a/lib/irccd/jsapi-system.h Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/jsapi-system.h Sat Jan 16 17:58:46 2021 +0100 @@ -19,9 +19,11 @@ #ifndef IRCCD_JSAPI_SYSTEM_H #define IRCCD_JSAPI_SYSTEM_H +#include <stdnoreturn.h> + #include <duktape.h> -void +void noreturn irc_jsapi_system_raise(duk_context *); void
--- a/lib/irccd/peer.c Sat Jan 16 09:45:33 2021 +0100 +++ b/lib/irccd/peer.c Sat Jan 16 17:58:46 2021 +0100 @@ -244,6 +244,8 @@ static int cmd_server_list(struct irc_peer *p, char *line) { + (void)line; + char out[IRC_BUF_MAX] = "OK "; for (struct irc_server *s = irc.servers; s; s = s->next) { @@ -300,6 +302,7 @@ const char *name; int (*call)(struct irc_peer *, char *); } cmds[] = { + { "SERVER-DISCONNECT", cmd_server_disconnect }, { "SERVER-INVITE", cmd_server_invite }, { "SERVER-JOIN", cmd_server_join }, { "SERVER-KICK", cmd_server_kick }, @@ -389,7 +392,7 @@ if ((ns = send(p->fd, p->out, len, 0)) < 0) return false; - if (ns >= len) + if ((size_t)ns >= len) memset(p->out, 0, sizeof (p->out)); else memmove(p->out, p->out + ns, sizeof (p->out) - ns); @@ -443,8 +446,6 @@ assert(p); assert(fd); - char buf[IRC_BUF_MAX]; - if (fd->fd != p->fd) return true;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/CMakeLists.txt Sat Jan 16 17:58:46 2021 +0100 @@ -0,0 +1,36 @@ +# +# CMakeLists.txt -- CMake build for irccd +# +# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(tests) + +set( + TESTS + test-channel + #test-dl-plugin + test-log + test-rule + test-subst + test-util +) + +foreach (t ${TESTS}) + add_executable(${t} ${t}.c) + add_test(${t} ${t}) + target_link_libraries(${t} libirccd libirccd-greatest) + set_target_properties(${t} PROPERTIES FOLDER "tests") +endforeach ()