diff --git a/.gitignore b/.gitignore index 7105e5a..ea53ea2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ ft_ping -ft_ping.test *.o *.d @@ -8,8 +7,26 @@ ft_ping.test *.swo *.bak *.log -build/ -build.mk .cache/ compile_commands.json includes/version_gen.h +tests/ft_ping_test +tests/ft_ping_test.trs + +# Automake build artifacts +**/.dirstamp + +# Autotools generated files +/aclocal.m4 +/configure +/build-aux/ +/m4/*.m4 +Makefile +Makefile.in +config.status +config.log +libtool +stamp-h1 +.deps/ +.libs/ +autom4te.cache/ diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..0db866e --- /dev/null +++ b/Makefile.am @@ -0,0 +1,15 @@ +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = libcli src + +if BUILD_TESTS +SUBDIRS += tests +endif + +# libicmp uses a simple Makefile (not Autotools); invoke it as a hook. +# The actual linking dependency is declared in src/ping/Makefile.am. +clean-local: + $(MAKE) -C $(top_srcdir)/libicmp clean + +distclean-local: + $(MAKE) -C $(top_srcdir)/libicmp fclean diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..a8855b7 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# autogen.sh - Generate Autotools build files + +set -e + +# Generate libcli configure first (it's an Autotools submodule) +if [ -f libcli/autogen.sh ]; then + echo "[autogen] Configuring libcli submodule..." + (cd libcli && ./autogen.sh) +fi + +echo "[autogen] Running autoreconf..." +autoreconf -fiv + +echo "[autogen] Done. Now run: ./configure && make" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..0f4a4e5 --- /dev/null +++ b/configure.ac @@ -0,0 +1,76 @@ +AC_PREREQ([2.69]) +AC_INIT([net-tools], [0.0.1], []) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIRS([m4]) +AM_INIT_AUTOMAKE([foreign -Wall subdir-objects]) + +# Compiler: prefer clang +AC_PROG_CC +if test "x$GCC" = "xyes" && test "x$CC" = "xgcc"; then + AC_CHECK_PROG([CLANG], [clang], [clang]) + if test -n "$CLANG"; then + CC="clang" + AC_MSG_NOTICE([Using clang]) + fi +fi +AM_PROG_AR +LT_PREREQ([2.2]) +LT_INIT + +# Strict flags — always enabled, not optional +STRICT_CFLAGS="-Wall -Wextra -Werror -Wpedantic -Wconversion -Wshadow" +AC_SUBST([STRICT_CFLAGS]) + +# libcli: Autotools submodule — configure automatically +AC_CONFIG_SUBDIRS([libcli]) + +# --enable-tests +AC_ARG_ENABLE([tests], + [AS_HELP_STRING([--enable-tests], [Build Criterion unit tests (default: no)])], + [enable_tests=$enableval], + [enable_tests=no]) +AM_CONDITIONAL([BUILD_TESTS], [test "x$enable_tests" = "xyes"]) +AS_IF([test "x$enable_tests" = "xyes"], [ + PKG_CHECK_MODULES([CRITERION], [criterion], [], [ + AC_MSG_NOTICE([pkg-config could not find criterion -- trying manual detection]) + AC_CHECK_HEADER([criterion/criterion.h], [], [ + AC_MSG_ERROR([criterion/criterion.h not found])]) + AC_CHECK_LIB([criterion], [main], + [CRITERION_LIBS="-lcriterion"], + [AC_MSG_ERROR([libcriterion not found])]) + ]) +]) + +# --enable-debug +AC_ARG_ENABLE([debug], + [AS_HELP_STRING([--enable-debug], [Enable debug build: -g -O0 (default: no)])], + [enable_debug=$enableval], + [enable_debug=no]) +AM_CONDITIONAL([ENABLE_DEBUG], [test "x$enable_debug" = "xyes"]) + +# --enable-sanitizers +AC_ARG_ENABLE([sanitizers], + [AS_HELP_STRING([--enable-sanitizers], + [Enable AddressSanitizer and UndefinedBehaviorSanitizer (default: no)])], + [enable_sanitizers=$enableval], + [enable_sanitizers=no]) +AM_CONDITIONAL([ENABLE_SANITIZERS], [test "x$enable_sanitizers" = "xyes"]) + +AC_CONFIG_FILES([ + Makefile + src/Makefile + src/ping/Makefile + tests/Makefile +]) +AC_OUTPUT + +AC_MSG_NOTICE([ + + net-tools $VERSION + ------------------ + CC : $CC + CFLAGS : $STRICT_CFLAGS + tests : $enable_tests + debug : $enable_debug + sanitizers : $enable_sanitizers +]) diff --git a/sources/cli.mk b/sources/cli.mk deleted file mode 100644 index 4fb24cf..0000000 --- a/sources/cli.mk +++ /dev/null @@ -1,6 +0,0 @@ - -CLI_SRC_DIR = src/cli -CLI_SRCS = $(CLI_SRC_DIR)/parse.c \ - $(CLI_SRC_DIR)/parse_utils/parse_int.c \ - $(CLI_SRC_DIR)/parse_utils/parse_float.c \ - diff --git a/sources/ping.mk b/sources/ping.mk deleted file mode 100644 index 68c2a47..0000000 --- a/sources/ping.mk +++ /dev/null @@ -1,68 +0,0 @@ - -include sources/cli.mk - -PING_SRC_DIR = src/ping -PING_SRCS = $(CLI_SRCS) \ - $(PING_SRC_DIR)/main.c \ - $(PING_SRC_DIR)/cli/parse.c \ - $(PING_SRC_DIR)/cli/handlers/handle_count.c \ - $(PING_SRC_DIR)/cli/handlers/handle_dont_fragment.c \ - $(PING_SRC_DIR)/cli/handlers/handle_deadline.c \ - $(PING_SRC_DIR)/cli/handlers/handle_flood.c \ - $(PING_SRC_DIR)/cli/handlers/handle_help.c \ - $(PING_SRC_DIR)/cli/handlers/handle_interval.c \ - $(PING_SRC_DIR)/cli/handlers/handle_quiet.c \ - $(PING_SRC_DIR)/cli/handlers/option_map.c \ - $(PING_SRC_DIR)/cli/handlers/handle_size.c \ - $(PING_SRC_DIR)/cli/handlers/handle_timeout.c \ - $(PING_SRC_DIR)/cli/handlers/handle_ttl.c \ - $(PING_SRC_DIR)/cli/handlers/handle_version.c \ - $(PING_SRC_DIR)/cli/handlers/handle_verbose.c \ - $(PING_SRC_DIR)/cli/parse_utils/parse_inet_addr.c \ - $(PING_SRC_DIR)/cli/parse_utils/parse_destinations.c \ - $(PING_SRC_DIR)/cli/config_free.c \ - $(PING_SRC_DIR)/cli/messages/help.c \ - $(PING_SRC_DIR)/cli/messages/version.c \ - $(PING_SRC_DIR)/cli/messages/error.c \ - $(PING_SRC_DIR)/core/ping.c \ - $(PING_SRC_DIR)/core/loop.c \ - $(PING_SRC_DIR)/core/send.c \ - $(PING_SRC_DIR)/core/callback.c \ - $(PING_SRC_DIR)/tracker/init.c \ - $(PING_SRC_DIR)/tracker/record_send.c \ - $(PING_SRC_DIR)/tracker/record_recv.c \ - $(PING_SRC_DIR)/output/start.c \ - $(PING_SRC_DIR)/output/packet.c \ - $(PING_SRC_DIR)/output/error.c \ - $(PING_SRC_DIR)/output/summary.c \ - $(PING_SRC_DIR)/output/flood.c \ - $(PING_SRC_DIR)/scheduler/scheduler_arm.c \ - $(PING_SRC_DIR)/scheduler/scheduler_select_tv.c \ - $(PING_SRC_DIR)/scheduler/scheduler_init.c \ - $(PING_SRC_DIR)/stats/stats_get.c \ - $(PING_SRC_DIR)/stats/stats_init.c \ - $(PING_SRC_DIR)/stats/stats_update.c \ - - -PING_TESTS_DIR = tests -PING_TESTS = $(PING_TESTS_DIR)/test_main.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_count.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_flood.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_help.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_interval.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_quiet.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handler_map.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_size.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_timeout.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_ttl.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_version.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_verbose.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_dont_fragment.c \ - $(PING_TESTS_DIR)/cli/handlers/test_handle_deadline.c \ - $(PING_TESTS_DIR)/cli/parse_utils/test_parse_int.c \ - $(PING_TESTS_DIR)/cli/parse_utils/test_parse_float.c \ - $(PING_TESTS_DIR)/cli/parse_utils/test_parse_inet_addr.c \ - $(PING_TESTS_DIR)/cli/parse_utils/test_parse_destinations.c \ - $(PING_TESTS_DIR)/ping/stats/test_stats.c \ - $(PING_TESTS_DIR)/ping/tracker/test_tracker.c \ - diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..8016aa9 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = ping diff --git a/src/ping/Makefile.am b/src/ping/Makefile.am new file mode 100644 index 0000000..6db6d04 --- /dev/null +++ b/src/ping/Makefile.am @@ -0,0 +1,119 @@ +bin_PROGRAMS = ft_ping + +PING_VERSION = 0.0.1 +VERSION_HEADER = $(top_srcdir)/includes/version_gen.h + +# Version header: generated at build time (embeds git hash + date) +BUILT_SOURCES = $(VERSION_HEADER) +CLEANFILES = $(VERSION_HEADER) + +$(VERSION_HEADER): FORCE + @NEW_HEADER=$$(mktemp); \ + PING_BUILD_DATE=$$(git -C $(top_srcdir) log -1 --format=%cd \ + --date=format:'%Y-%m-%d %H:%M:%S' 2>/dev/null \ + || date -u '+%Y-%m-%d %H:%M:%S'); \ + PING_GIT_COMMIT=$$(git -C $(top_srcdir) rev-parse --short HEAD 2>/dev/null \ + || echo "nogit"); \ + if test "$$PING_GIT_COMMIT" = "nogit"; then \ + HAS_GIT=0; \ + else \ + HAS_GIT=1; \ + fi; \ + echo "/* Auto-generated - DO NOT EDIT */" > $$NEW_HEADER; \ + echo "#ifndef PING_VERSION_GEN_H" >> $$NEW_HEADER; \ + echo "#define PING_VERSION_GEN_H" >> $$NEW_HEADER; \ + echo "#define PING_VERSION \"$(PING_VERSION)\"" >> $$NEW_HEADER; \ + echo "#define PING_BUILD_DATE \"$$PING_BUILD_DATE\"" >> $$NEW_HEADER; \ + echo "#define PING_GIT_COMMIT \"$$PING_GIT_COMMIT\"" >> $$NEW_HEADER; \ + echo "#define PING_HAS_GIT_COMMIT $$HAS_GIT" >> $$NEW_HEADER; \ + echo "" >> $$NEW_HEADER; \ + echo "struct prog_name" >> $$NEW_HEADER; \ + echo "{" >> $$NEW_HEADER; \ + echo " char *alloc;" >> $$NEW_HEADER; \ + echo " const char *name;" >> $$NEW_HEADER; \ + echo "};" >> $$NEW_HEADER; \ + echo "" >> $$NEW_HEADER; \ + echo "extern struct prog_name g_prog_name;" >> $$NEW_HEADER; \ + echo "" >> $$NEW_HEADER; \ + echo "#endif" >> $$NEW_HEADER; \ + if test ! -f $(VERSION_HEADER) || ! cmp -s $$NEW_HEADER $(VERSION_HEADER); then \ + mv $$NEW_HEADER $(VERSION_HEADER); \ + echo "[OK] Version header generated"; \ + else \ + rm -f $$NEW_HEADER; \ + fi + +FORCE: +.PHONY: FORCE + +ft_ping_SOURCES = \ + main.c \ + cli/parse.c \ + cli/handlers/handle_count.c \ + cli/handlers/handle_dont_fragment.c \ + cli/handlers/handle_deadline.c \ + cli/handlers/handle_flood.c \ + cli/handlers/handle_help.c \ + cli/handlers/handle_interval.c \ + cli/handlers/handle_quiet.c \ + cli/handlers/option_map.c \ + cli/handlers/handle_size.c \ + cli/handlers/handle_timeout.c \ + cli/handlers/handle_ttl.c \ + cli/handlers/handle_version.c \ + cli/handlers/handle_verbose.c \ + cli/parse_utils/parse_inet_addr.c \ + cli/parse_utils/parse_destinations.c \ + cli/config_free.c \ + cli/messages/help.c \ + cli/messages/version.c \ + cli/messages/error.c \ + core/ping.c \ + core/loop.c \ + core/send.c \ + core/callback.c \ + tracker/init.c \ + tracker/record_send.c \ + tracker/record_recv.c \ + output/start.c \ + output/packet.c \ + output/error.c \ + output/summary.c \ + output/flood.c \ + scheduler/scheduler_arm.c \ + scheduler/scheduler_select_tv.c \ + scheduler/scheduler_init.c \ + stats/stats_get.c \ + stats/stats_init.c \ + stats/stats_update.c + +ft_ping_CPPFLAGS = \ + -I $(top_srcdir)/includes \ + -I $(top_srcdir)/libicmp/includes \ + -I $(top_srcdir)/libcli/include \ + -D_GNU_SOURCE + +BASE_CFLAGS = -std=c99 $(STRICT_CFLAGS) + +if ENABLE_DEBUG +EXTRA_CFLAGS = -g -O0 +else +EXTRA_CFLAGS = +endif + +if ENABLE_SANITIZERS +SANITIZER_FLAGS = -fsanitize=address,undefined +else +SANITIZER_FLAGS = +endif + +ft_ping_CFLAGS = $(BASE_CFLAGS) $(EXTRA_CFLAGS) $(SANITIZER_FLAGS) +ft_ping_LDFLAGS = $(SANITIZER_FLAGS) +ft_ping_LDADD = \ + $(top_srcdir)/libicmp/libicmp.a \ + $(top_builddir)/libcli/src/libcli.la \ + -lm + +# Build libicmp (simple Makefile) before linking +$(top_srcdir)/libicmp/libicmp.a: + $(MAKE) -C $(top_srcdir)/libicmp BUILD_STATIC=yes BUILD_SHARED=no diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..4911418 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,83 @@ +check_PROGRAMS = ft_ping_test + +ft_ping_test_SOURCES = \ + test_main.c \ + cli/handlers/test_handle_count.c \ + cli/handlers/test_handle_flood.c \ + cli/handlers/test_handle_help.c \ + cli/handlers/test_handle_interval.c \ + cli/handlers/test_handle_quiet.c \ + cli/handlers/test_handler_map.c \ + cli/handlers/test_handle_size.c \ + cli/handlers/test_handle_timeout.c \ + cli/handlers/test_handle_ttl.c \ + cli/handlers/test_handle_version.c \ + cli/handlers/test_handle_verbose.c \ + cli/handlers/test_handle_dont_fragment.c \ + cli/handlers/test_handle_deadline.c \ + cli/parse_utils/test_parse_int.c \ + cli/parse_utils/test_parse_float.c \ + cli/parse_utils/test_parse_inet_addr.c \ + cli/parse_utils/test_parse_destinations.c \ + ping/stats/test_stats.c \ + ping/tracker/test_tracker.c \ + $(top_srcdir)/src/ping/cli/parse.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_count.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_dont_fragment.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_deadline.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_flood.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_help.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_interval.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_quiet.c \ + $(top_srcdir)/src/ping/cli/handlers/option_map.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_size.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_timeout.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_ttl.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_version.c \ + $(top_srcdir)/src/ping/cli/handlers/handle_verbose.c \ + $(top_srcdir)/src/ping/cli/parse_utils/parse_inet_addr.c \ + $(top_srcdir)/src/ping/cli/parse_utils/parse_destinations.c \ + $(top_srcdir)/src/ping/cli/config_free.c \ + $(top_srcdir)/src/ping/cli/messages/help.c \ + $(top_srcdir)/src/ping/cli/messages/version.c \ + $(top_srcdir)/src/ping/cli/messages/error.c \ + $(top_srcdir)/src/ping/tracker/init.c \ + $(top_srcdir)/src/ping/tracker/record_send.c \ + $(top_srcdir)/src/ping/tracker/record_recv.c \ + $(top_srcdir)/src/ping/stats/stats_get.c \ + $(top_srcdir)/src/ping/stats/stats_init.c \ + $(top_srcdir)/src/ping/stats/stats_update.c + +ft_ping_test_CPPFLAGS = \ + -I $(top_srcdir)/includes \ + -I $(top_srcdir)/libicmp/includes \ + -I $(top_srcdir)/libcli/include \ + -I $(top_srcdir)/tests \ + -D_GNU_SOURCE + +BASE_CFLAGS = -std=c99 $(STRICT_CFLAGS) + +if ENABLE_DEBUG +EXTRA_CFLAGS = -g -O0 +else +EXTRA_CFLAGS = +endif + +if ENABLE_SANITIZERS +SANITIZER_FLAGS = -fsanitize=address,undefined +else +SANITIZER_FLAGS = +endif + +ft_ping_test_CFLAGS = $(BASE_CFLAGS) $(EXTRA_CFLAGS) $(SANITIZER_FLAGS) +ft_ping_test_LDFLAGS = $(SANITIZER_FLAGS) +ft_ping_test_LDADD = \ + $(top_srcdir)/libicmp/libicmp.a \ + $(top_builddir)/libcli/src/libcli.la \ + $(CRITERION_LIBS) \ + -lm + +TESTS = ft_ping_test + +# Version header needed by test_main.c +BUILT_SOURCES = $(top_srcdir)/includes/version_gen.h